|
20 | 20 | #include "test_helper.h" |
21 | 21 | #include "test_macros.h" |
22 | 22 |
|
23 | | -template <typename U> |
| 23 | +template <typename T> |
24 | 24 | struct TestAssign { |
25 | 25 | void operator()() const { |
26 | | - static_assert(std::is_nothrow_assignable_v<std::atomic_ref<U>, U>); |
27 | | - do_test<U>(); |
28 | | - do_test_atomic<U>(); |
29 | | - static_assert(!std::is_assignable_v<std::atomic_ref<U const>, U>); |
30 | | - if constexpr (std::atomic_ref<U>::is_always_lock_free) { |
31 | | - static_assert(std::is_nothrow_assignable_v<std::atomic_ref<U volatile>, U>); |
32 | | - do_test<U volatile>(); |
33 | | - do_test_atomic<U volatile>(); |
34 | | - static_assert(!std::is_assignable_v<std::atomic_ref<U const volatile>, U>); |
35 | | - } |
36 | | - } |
| 26 | + using Unqualified = std::remove_cv_t<T>; |
| 27 | + static_assert(std::is_assignable_v<std::atomic_ref<T>, Unqualified> == !std::is_const_v<T>); |
37 | 28 |
|
38 | | - template <typename T> |
39 | | - void do_test() const { |
40 | | - T x(T(1)); |
41 | | - std::atomic_ref<T> const a(x); |
| 29 | + if constexpr (!std::is_const_v<T>) { |
| 30 | + { |
| 31 | + T x(Unqualified(1)); |
| 32 | + std::atomic_ref<T> const a(x); |
42 | 33 |
|
43 | | - std::same_as<std::remove_cv_t<T>> decltype(auto) y = (a = T(2)); |
44 | | - assert(y == std::remove_cv_t<T>(2)); |
45 | | - assert(const_cast<std::remove_cv_t<T> const&>(x) == std::remove_cv_t<T>(2)); |
| 34 | + std::same_as<Unqualified> decltype(auto) y = (a = Unqualified(2)); |
| 35 | + assert(y == Unqualified(2)); |
| 36 | + assert(const_cast<Unqualified const&>(x) == Unqualified(2)); |
46 | 37 |
|
47 | | - ASSERT_NOEXCEPT(a = T(0)); |
| 38 | + ASSERT_NOEXCEPT(a = Unqualified(0)); |
| 39 | + static_assert(std::is_nothrow_assignable_v<std::atomic_ref<T>, Unqualified>); |
| 40 | + static_assert(!std::is_copy_assignable_v<std::atomic_ref<T>>); |
| 41 | + } |
48 | 42 |
|
49 | | - static_assert(!std::is_copy_assignable_v<std::atomic_ref<T>>); |
| 43 | + { |
| 44 | + auto assign = [](std::atomic_ref<T> const& y, T const&, T const& new_val) { |
| 45 | + y = const_cast<Unqualified const&>(new_val); |
| 46 | + }; |
| 47 | + auto load = [](std::atomic_ref<T> const& y) { return y.load(); }; |
| 48 | + test_seq_cst<T>(assign, load); |
| 49 | + } |
| 50 | + } |
50 | 51 | } |
| 52 | +}; |
51 | 53 |
|
52 | | - template <typename T> |
53 | | - void do_test_atomic() const { |
54 | | - { |
55 | | - auto assign = [](std::atomic_ref<T> const& y, T const&, T const& new_val) { |
56 | | - y = const_cast<std::remove_cv_t<T> const&>(new_val); |
57 | | - }; |
58 | | - auto load = [](std::atomic_ref<T> const& y) { return y.load(); }; |
59 | | - test_seq_cst<T>(assign, load); |
| 54 | +template <template <class...> class F> |
| 55 | +struct CallWithCVQualifiers { |
| 56 | + template <class T> |
| 57 | + struct apply { |
| 58 | + void operator()() const { |
| 59 | + F<T>()(); |
| 60 | + F<T const>()(); |
| 61 | + if constexpr (std::atomic_ref<T>::is_always_lock_free) { |
| 62 | + F<T volatile>()(); |
| 63 | + F<T const volatile>()(); |
| 64 | + } |
60 | 65 | } |
61 | | - } |
| 66 | + }; |
62 | 67 | }; |
63 | 68 |
|
64 | 69 | int main(int, char**) { |
65 | | - TestEachAtomicType<TestAssign>()(); |
| 70 | + TestEachAtomicType<CallWithCVQualifiers<TestAssign>::apply>()(); |
66 | 71 | return 0; |
67 | 72 | } |
0 commit comments