Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions include/stdx/atomic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,22 @@ template <typename T> class atomic {
using elem_t = ::atomic::atomic_type_t<T>;
constexpr static auto alignment = ::atomic::alignment_of<T>;

static_assert(std::is_convertible_v<elem_t, T>,
static_assert(std::is_trivially_copyable_v<T>,
"value_type of atomic<T> must be trivially_copyable");
static_assert(std::is_trivially_copyable_v<elem_t>,
"::atomic::atomic_type_t specialization result must be "
"convertible to T");
static_assert(std::is_convertible_v<T, elem_t>,
"trivially_copyable");

static_assert(sizeof(elem_t) >= sizeof(T),
"::atomic::atomic_type_t specialization result must be at "
"least as big as T");
static_assert(alignof(elem_t) >= alignof(T),
"::atomic::atomic_type_t specialization result must be "
"alignment-compatible with T");

static_assert(alignof(elem_t) <= alignment,
"::atomic::atomic_type_t specialization result must be "
"convertible from T");
"alignment-compatible with alignment_of<T>");

alignas(alignment) elem_t value;

Expand Down
18 changes: 18 additions & 0 deletions test/atomic_override.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,21 @@ TEST_CASE("atomic works with overridden type", "[atomic_override]") {
CHECK(!bs.exchange(true));
CHECK(bs);
}

TEST_CASE("atomic config works with partial specialization",
"[atomic_override]") {
using elem_t = ::atomic::atomic_type_t<int *>;
static_assert(std::is_same_v<elem_t, uintptr_t>);
}

#if __cplusplus >= 202002L
namespace {
enum E : std::uint8_t {};
}

TEST_CASE("atomic config works with enum", "[atomic_override]") {
auto bs = stdx::atomic<E>{};
static_assert(sizeof(decltype(bs)) == sizeof(std::uint32_t));
static_assert(alignof(decltype(bs)) == alignof(std::uint32_t));
}
#endif
11 changes: 11 additions & 0 deletions test/detail/atomic_cfg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,14 @@ template <> struct atomic::atomic_type<std::uint8_t> {
template <> struct atomic::atomic_type<bool> {
using type = std::uint32_t;
};

template <typename T> struct atomic::atomic_type<T *> {
using type = std::uintptr_t;
};

#if __cplusplus >= 202002L
template <typename T>
requires(std::is_enum_v<T>)
struct atomic::atomic_type<T> : atomic::atomic_type<std::underlying_type_t<T>> {
};
#endif