diff --git a/include/stdx/atomic.hpp b/include/stdx/atomic.hpp index efc3ebb..48fa7e7 100644 --- a/include/stdx/atomic.hpp +++ b/include/stdx/atomic.hpp @@ -27,12 +27,22 @@ template class atomic { using elem_t = ::atomic::atomic_type_t; constexpr static auto alignment = ::atomic::alignment_of; - static_assert(std::is_convertible_v, + static_assert(std::is_trivially_copyable_v, + "value_type of atomic must be trivially_copyable"); + static_assert(std::is_trivially_copyable_v, "::atomic::atomic_type_t specialization result must be " - "convertible to T"); - static_assert(std::is_convertible_v, + "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"); alignas(alignment) elem_t value; diff --git a/test/atomic_override.cpp b/test/atomic_override.cpp index 5774661..ff14348 100644 --- a/test/atomic_override.cpp +++ b/test/atomic_override.cpp @@ -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; + static_assert(std::is_same_v); +} + +#if __cplusplus >= 202002L +namespace { +enum E : std::uint8_t {}; +} + +TEST_CASE("atomic config works with enum", "[atomic_override]") { + auto bs = stdx::atomic{}; + static_assert(sizeof(decltype(bs)) == sizeof(std::uint32_t)); + static_assert(alignof(decltype(bs)) == alignof(std::uint32_t)); +} +#endif diff --git a/test/detail/atomic_cfg.hpp b/test/detail/atomic_cfg.hpp index 3ac9212..e58f1fd 100644 --- a/test/detail/atomic_cfg.hpp +++ b/test/detail/atomic_cfg.hpp @@ -10,3 +10,14 @@ template <> struct atomic::atomic_type { template <> struct atomic::atomic_type { using type = std::uint32_t; }; + +template struct atomic::atomic_type { + using type = std::uintptr_t; +}; + +#if __cplusplus >= 202002L +template + requires(std::is_enum_v) +struct atomic::atomic_type : atomic::atomic_type> { +}; +#endif