|
29 | 29 | # include <thread> |
30 | 30 | #endif |
31 | 31 |
|
32 | | -template <class A, bool Integral> |
33 | | -struct test_atomic |
34 | | -{ |
35 | | - test_atomic() |
36 | | - { |
37 | | - A a; (void)a; |
| 32 | +// detect existence of the difference_type member type |
| 33 | +template <class...> |
| 34 | +using myvoid_t = void; |
| 35 | +template <typename T, typename = void> |
| 36 | +struct has_difference_type : std::false_type {}; |
| 37 | +template <typename T> |
| 38 | +struct has_difference_type<T, myvoid_t<typename T::difference_type> > : std::true_type {}; |
| 39 | + |
| 40 | +template <class A, bool IntegralOrFloating, bool Pointer> |
| 41 | +struct test_atomic { |
| 42 | + test_atomic() { |
| 43 | + static_assert(!IntegralOrFloating || !Pointer, ""); |
| 44 | + A a; |
| 45 | + (void)a; |
38 | 46 | #if TEST_STD_VER >= 17 |
39 | 47 | static_assert((std::is_same_v<typename A::value_type, decltype(a.load())>), ""); |
| 48 | + static_assert(!has_difference_type<A>::value, ""); |
40 | 49 | #endif |
41 | | - } |
| 50 | + } |
42 | 51 | }; |
43 | 52 |
|
44 | 53 | template <class A> |
45 | | -struct test_atomic<A, true> |
46 | | -{ |
47 | | - test_atomic() |
48 | | - { |
49 | | - A a; (void)a; |
| 54 | +struct test_atomic<A, true, false> { |
| 55 | + test_atomic() { |
| 56 | + A a; |
| 57 | + (void)a; |
50 | 58 | #if TEST_STD_VER >= 17 |
51 | 59 | static_assert((std::is_same_v<typename A::value_type, decltype(a.load())>), ""); |
52 | 60 | static_assert((std::is_same_v<typename A::value_type, typename A::difference_type>), ""); |
53 | 61 | #endif |
54 | | - } |
| 62 | + } |
55 | 63 | }; |
56 | 64 |
|
57 | 65 | template <class A> |
58 | | -struct test_atomic<A*, false> |
59 | | -{ |
60 | | - test_atomic() |
61 | | - { |
62 | | - A a; (void)a; |
| 66 | +struct test_atomic<A, false, true> { |
| 67 | + test_atomic() { |
| 68 | + A a; |
| 69 | + (void)a; |
63 | 70 | #if TEST_STD_VER >= 17 |
64 | 71 | static_assert((std::is_same_v<typename A::value_type, decltype(a.load())>), ""); |
65 | 72 | static_assert((std::is_same_v<typename A::difference_type, std::ptrdiff_t>), ""); |
66 | 73 | #endif |
67 | | - } |
| 74 | + } |
68 | 75 | }; |
69 | 76 |
|
70 | 77 | template <class T> |
71 | | -void |
72 | | -test() |
73 | | -{ |
74 | | - using A = std::atomic<T>; |
| 78 | +void test() { |
| 79 | + using A = std::atomic<T>; |
75 | 80 | #if TEST_STD_VER >= 17 |
76 | | - static_assert((std::is_same_v<typename A::value_type, T>), ""); |
| 81 | + static_assert((std::is_same_v<typename A::value_type, T>), ""); |
77 | 82 | #endif |
78 | | - test_atomic<A, std::is_integral<T>::value && !std::is_same<T, bool>::value>(); |
| 83 | + constexpr bool IntegralOrFloating = |
| 84 | + (std::is_integral<T>::value && !std::is_same<T, bool>::value) || std::is_floating_point<T>::value; |
| 85 | + constexpr bool Pointer = std::is_pointer<T>::value; |
| 86 | + test_atomic<A, IntegralOrFloating, Pointer>(); |
79 | 87 | } |
80 | 88 |
|
81 | 89 | struct TriviallyCopyable { |
82 | | - int i_; |
| 90 | + int i_; |
83 | 91 | }; |
84 | 92 |
|
85 | | -struct WeirdTriviallyCopyable |
86 | | -{ |
87 | | - char i, j, k; /* the 3 chars of doom */ |
| 93 | +struct WeirdTriviallyCopyable { |
| 94 | + char i, j, k; /* the 3 chars of doom */ |
88 | 95 | }; |
89 | 96 |
|
90 | | -struct PaddedTriviallyCopyable |
91 | | -{ |
92 | | - char i; int j; /* probably lock-free? */ |
| 97 | +struct PaddedTriviallyCopyable { |
| 98 | + char i; |
| 99 | + int j; /* probably lock-free? */ |
93 | 100 | }; |
94 | 101 |
|
95 | | -struct LargeTriviallyCopyable |
96 | | -{ |
97 | | - int i, j[127]; /* decidedly not lock-free */ |
| 102 | +struct LargeTriviallyCopyable { |
| 103 | + int i, j[127]; /* decidedly not lock-free */ |
98 | 104 | }; |
99 | 105 |
|
100 | | -int main(int, char**) |
101 | | -{ |
102 | | - test<bool> (); |
103 | | - test<char> (); |
104 | | - test<signed char> (); |
105 | | - test<unsigned char> (); |
106 | | - test<short> (); |
107 | | - test<unsigned short> (); |
108 | | - test<int> (); |
109 | | - test<unsigned int> (); |
110 | | - test<long> (); |
111 | | - test<unsigned long> (); |
112 | | - test<long long> (); |
113 | | - test<unsigned long long> (); |
| 106 | +int main(int, char**) { |
| 107 | + test<bool>(); |
| 108 | + test<char>(); |
| 109 | + test<signed char>(); |
| 110 | + test<unsigned char>(); |
| 111 | + test<short>(); |
| 112 | + test<unsigned short>(); |
| 113 | + test<int>(); |
| 114 | + test<unsigned int>(); |
| 115 | + test<long>(); |
| 116 | + test<unsigned long>(); |
| 117 | + test<long long>(); |
| 118 | + test<unsigned long long>(); |
114 | 119 | #if TEST_STD_VER > 17 && defined(__cpp_char8_t) |
115 | | - test<char8_t> (); |
| 120 | + test<char8_t>(); |
116 | 121 | #endif |
117 | | - test<char16_t> (); |
118 | | - test<char32_t> (); |
| 122 | + test<char16_t>(); |
| 123 | + test<char32_t>(); |
119 | 124 | #ifndef TEST_HAS_NO_WIDE_CHARACTERS |
120 | | - test<wchar_t> (); |
| 125 | + test<wchar_t>(); |
121 | 126 | #endif |
122 | 127 |
|
123 | | - test<std::int_least8_t> (); |
124 | | - test<std::uint_least8_t> (); |
125 | | - test<std::int_least16_t> (); |
126 | | - test<std::uint_least16_t> (); |
127 | | - test<std::int_least32_t> (); |
128 | | - test<std::uint_least32_t> (); |
129 | | - test<std::int_least64_t> (); |
130 | | - test<std::uint_least64_t> (); |
131 | | - |
132 | | - test<std::int_fast8_t> (); |
133 | | - test<std::uint_fast8_t> (); |
134 | | - test<std::int_fast16_t> (); |
135 | | - test<std::uint_fast16_t> (); |
136 | | - test<std::int_fast32_t> (); |
137 | | - test<std::uint_fast32_t> (); |
138 | | - test<std::int_fast64_t> (); |
139 | | - test<std::uint_fast64_t> (); |
140 | | - |
141 | | - test< std::int8_t> (); |
142 | | - test<std::uint8_t> (); |
143 | | - test< std::int16_t> (); |
144 | | - test<std::uint16_t> (); |
145 | | - test< std::int32_t> (); |
146 | | - test<std::uint32_t> (); |
147 | | - test< std::int64_t> (); |
148 | | - test<std::uint64_t> (); |
149 | | - |
150 | | - test<std::intptr_t> (); |
151 | | - test<std::uintptr_t> (); |
152 | | - test<std::size_t> (); |
153 | | - test<std::ptrdiff_t> (); |
154 | | - test<std::intmax_t> (); |
155 | | - test<std::uintmax_t> (); |
156 | | - |
157 | | - test<std::uintmax_t> (); |
158 | | - test<std::uintmax_t> (); |
159 | | - |
160 | | - test<TriviallyCopyable>(); |
161 | | - test<PaddedTriviallyCopyable>(); |
| 128 | + test<std::int_least8_t>(); |
| 129 | + test<std::uint_least8_t>(); |
| 130 | + test<std::int_least16_t>(); |
| 131 | + test<std::uint_least16_t>(); |
| 132 | + test<std::int_least32_t>(); |
| 133 | + test<std::uint_least32_t>(); |
| 134 | + test<std::int_least64_t>(); |
| 135 | + test<std::uint_least64_t>(); |
| 136 | + |
| 137 | + test<std::int_fast8_t>(); |
| 138 | + test<std::uint_fast8_t>(); |
| 139 | + test<std::int_fast16_t>(); |
| 140 | + test<std::uint_fast16_t>(); |
| 141 | + test<std::int_fast32_t>(); |
| 142 | + test<std::uint_fast32_t>(); |
| 143 | + test<std::int_fast64_t>(); |
| 144 | + test<std::uint_fast64_t>(); |
| 145 | + |
| 146 | + test< std::int8_t>(); |
| 147 | + test<std::uint8_t>(); |
| 148 | + test< std::int16_t>(); |
| 149 | + test<std::uint16_t>(); |
| 150 | + test< std::int32_t>(); |
| 151 | + test<std::uint32_t>(); |
| 152 | + test< std::int64_t>(); |
| 153 | + test<std::uint64_t>(); |
| 154 | + |
| 155 | + test<std::intptr_t>(); |
| 156 | + test<std::uintptr_t>(); |
| 157 | + test<std::size_t>(); |
| 158 | + test<std::ptrdiff_t>(); |
| 159 | + test<std::intmax_t>(); |
| 160 | + test<std::uintmax_t>(); |
| 161 | + |
| 162 | + test<std::uintmax_t>(); |
| 163 | + test<std::uintmax_t>(); |
| 164 | + |
| 165 | + test<void*>(); |
| 166 | + test<const void*>(); |
| 167 | + test<int*>(); |
| 168 | + test<const int*>(); |
| 169 | + |
| 170 | + test<TriviallyCopyable>(); |
| 171 | + test<PaddedTriviallyCopyable>(); |
162 | 172 | #ifndef __APPLE__ // Apple doesn't ship libatomic |
163 | | - /* |
| 173 | + /* |
164 | 174 | These aren't going to be lock-free, |
165 | 175 | so some libatomic.a is necessary. |
166 | 176 | */ |
167 | | - test<WeirdTriviallyCopyable>(); |
168 | | - test<LargeTriviallyCopyable>(); |
| 177 | + test<WeirdTriviallyCopyable>(); |
| 178 | + test<LargeTriviallyCopyable>(); |
169 | 179 | #endif |
170 | 180 |
|
171 | 181 | #ifndef TEST_HAS_NO_THREADS |
172 | | - test<std::thread::id>(); |
| 182 | + test<std::thread::id>(); |
173 | 183 | #endif |
174 | | - test<std::chrono::nanoseconds>(); |
175 | | - test<float>(); |
| 184 | + test<std::chrono::nanoseconds>(); |
| 185 | + test<float>(); |
176 | 186 |
|
177 | 187 | #if TEST_STD_VER >= 20 |
178 | | - test<std::atomic_signed_lock_free::value_type>(); |
179 | | - static_assert(std::is_signed_v<std::atomic_signed_lock_free::value_type>); |
180 | | - static_assert(std::is_integral_v<std::atomic_signed_lock_free::value_type>); |
| 188 | + test<std::atomic_signed_lock_free::value_type>(); |
| 189 | + static_assert(std::is_signed_v<std::atomic_signed_lock_free::value_type>); |
| 190 | + static_assert(std::is_integral_v<std::atomic_signed_lock_free::value_type>); |
181 | 191 |
|
182 | | - test<std::atomic_unsigned_lock_free::value_type>(); |
183 | | - static_assert(std::is_unsigned_v<std::atomic_unsigned_lock_free::value_type>); |
184 | | - static_assert(std::is_integral_v<std::atomic_unsigned_lock_free::value_type>); |
| 192 | + test<std::atomic_unsigned_lock_free::value_type>(); |
| 193 | + static_assert(std::is_unsigned_v<std::atomic_unsigned_lock_free::value_type>); |
| 194 | + static_assert(std::is_integral_v<std::atomic_unsigned_lock_free::value_type>); |
185 | 195 | /* |
186 | 196 | test<std::shared_ptr<int>>(); |
187 | 197 | */ |
188 | 198 | #endif |
189 | 199 |
|
190 | | - return 0; |
| 200 | + return 0; |
191 | 201 | } |
0 commit comments