Skip to content

🐛 Make atomic config work with scoped enumerations #210

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 20, 2025
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