88
99#include < atomic>
1010#include < cassert>
11+ #include < cstddef>
1112#include < cstdint>
1213#include < cstdlib>
1314#include < cstring>
@@ -20,14 +21,18 @@ using namespace std;
2021
2122#define STATIC_ASSERT (...) static_assert (__VA_ARGS__, #__VA_ARGS__)
2223
23- // N3797 29.6.5 [atomics.types.operations.req]/21:
24- // bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile noexcept;
25- // bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst) noexcept;
26- // bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile
27- // noexcept; bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst)
28- // noexcept; When only one memory_order argument is supplied, the value of success is order, and the value of failure is
29- // order except that a value of memory_order_acq_rel shall be replaced by the value memory_order_acquire and a value of
30- // memory_order_release shall be replaced by the value memory_order_relaxed.
24+ // N4981 [atomics.types.operations]/23:
25+ // bool compare_exchange_weak(T& expected, T desired,
26+ // memory_order order = memory_order::seq_cst) volatile noexcept;
27+ // bool compare_exchange_weak(T& expected, T desired,
28+ // memory_order order = memory_order::seq_cst) noexcept;
29+ // bool compare_exchange_strong(T& expected, T desired,
30+ // memory_order order = memory_order::seq_cst) volatile noexcept;
31+ // bool compare_exchange_strong(T& expected, T desired,
32+ // memory_order order = memory_order::seq_cst) noexcept;
33+ // When only one memory_order argument is supplied, the value of success is order, and the value of failure is order
34+ // except that a value of memory_order::acq_rel shall be replaced by the value memory_order::acquire and a value of
35+ // memory_order::release shall be replaced by the value memory_order::relaxed.
3136
3237template <typename T>
3338void test (T t) {
@@ -553,6 +558,57 @@ void test_double_identical_results() {
553558#endif // _HAS_CXX20
554559}
555560
561+ // Also test GH-4688 "<atomic>: atomic_ref<void*> and atomic<void*> lack difference_type"
562+ template <class , class = void >
563+ constexpr bool atomic_has_member_difference_type = false ;
564+ template <class T >
565+ constexpr bool atomic_has_member_difference_type<T, void_t <typename atomic<T>::difference_type>> = true ;
566+
567+ STATIC_ASSERT (is_same_v<atomic<signed char >::difference_type, signed char >);
568+ STATIC_ASSERT (is_same_v<atomic<short >::difference_type, short >);
569+ STATIC_ASSERT (is_same_v<atomic<int >::difference_type, int >);
570+ STATIC_ASSERT (is_same_v<atomic<long >::difference_type, long >);
571+ STATIC_ASSERT (is_same_v<atomic<long long >::difference_type, long long >);
572+ STATIC_ASSERT (is_same_v<atomic<unsigned char >::difference_type, unsigned char >);
573+ STATIC_ASSERT (is_same_v<atomic<unsigned short >::difference_type, unsigned short >);
574+ STATIC_ASSERT (is_same_v<atomic<unsigned int >::difference_type, unsigned int >);
575+ STATIC_ASSERT (is_same_v<atomic<unsigned long >::difference_type, unsigned long >);
576+ STATIC_ASSERT (is_same_v<atomic<unsigned long long >::difference_type, unsigned long long >);
577+ STATIC_ASSERT (is_same_v<atomic<char >::difference_type, char >);
578+ #ifdef __cpp_char8_t
579+ STATIC_ASSERT (is_same_v<atomic<char8_t >::difference_type, char8_t >);
580+ #endif // defined(__cpp_char8_t)
581+ STATIC_ASSERT (is_same_v<atomic<char16_t >::difference_type, char16_t >);
582+ STATIC_ASSERT (is_same_v<atomic<char32_t >::difference_type, char32_t >);
583+ STATIC_ASSERT (is_same_v<atomic<wchar_t >::difference_type, wchar_t >);
584+
585+ #if _HAS_CXX20 // P0020R6 Floating Point Atomic
586+ STATIC_ASSERT (is_same_v<atomic<float >::difference_type, float >);
587+ STATIC_ASSERT (is_same_v<atomic<double >::difference_type, double >);
588+ STATIC_ASSERT (is_same_v<atomic<long double >::difference_type, long double >);
589+ #else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
590+ STATIC_ASSERT (!atomic_has_member_difference_type<float >);
591+ STATIC_ASSERT (!atomic_has_member_difference_type<double >);
592+ STATIC_ASSERT (!atomic_has_member_difference_type<long double >);
593+ #endif // ^^^ !_HAS_CXX20 ^^^
594+
595+ STATIC_ASSERT (is_same_v<atomic<int *>::difference_type, ptrdiff_t >);
596+ STATIC_ASSERT (is_same_v<atomic<bool *>::difference_type, ptrdiff_t >);
597+ STATIC_ASSERT (is_same_v<atomic<const int *>::difference_type, ptrdiff_t >);
598+ STATIC_ASSERT (is_same_v<atomic<volatile bool *>::difference_type, ptrdiff_t >);
599+
600+ STATIC_ASSERT (is_same_v<atomic<void *>::difference_type, ptrdiff_t >);
601+ STATIC_ASSERT (is_same_v<atomic<const void *>::difference_type, ptrdiff_t >);
602+ STATIC_ASSERT (is_same_v<atomic<volatile void *>::difference_type, ptrdiff_t >);
603+ STATIC_ASSERT (is_same_v<atomic<const volatile void *>::difference_type, ptrdiff_t >);
604+ STATIC_ASSERT (is_same_v<atomic<void (*)()>::difference_type, ptrdiff_t >);
605+
606+ STATIC_ASSERT (!atomic_has_member_difference_type<bool >);
607+ STATIC_ASSERT (!atomic_has_member_difference_type<nullptr_t >);
608+ STATIC_ASSERT (!atomic_has_member_difference_type<Bytes<4 >>);
609+ STATIC_ASSERT (!atomic_has_member_difference_type<Bytes<8 >>);
610+ STATIC_ASSERT (!atomic_has_member_difference_type<Bytes<12 >>);
611+
556612int main () {
557613 X x = {1729 };
558614 test (x);
0 commit comments