| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 |
| |
| // <atomic> |
| |
| // template <class T> |
| // struct atomic_ref |
| // { |
| // using value_type = T; |
| // using difference_type = value_type; // only for atomic_ref<Integral> and |
| // // atomic_ref<Floating> specializations |
| // using difference_type = std::ptrdiff_t; // only for atomic_ref<T*> specializations |
| // |
| // explicit atomic_ref(T&); |
| // atomic_ref(const atomic_ref&) noexcept; |
| // atomic_ref& operator=(const atomic_ref&) = delete; |
| // }; |
| |
| #include <atomic> |
| #include <type_traits> |
| |
| #include "test_macros.h" |
| |
| template <class T> |
| concept has_difference_type = requires { typename T::difference_type; }; |
| |
| template <class T> |
| void check_member_types() { |
| if constexpr ((std::is_integral_v<T> && !std::is_same_v<T, bool>) || std::is_floating_point_v<T>) { |
| ASSERT_SAME_TYPE(typename std::atomic_ref<T>::value_type, T); |
| ASSERT_SAME_TYPE(typename std::atomic_ref<T>::difference_type, T); |
| } else if constexpr (std::is_pointer_v<T>) { |
| ASSERT_SAME_TYPE(typename std::atomic_ref<T>::value_type, T); |
| ASSERT_SAME_TYPE(typename std::atomic_ref<T>::difference_type, std::ptrdiff_t); |
| } else { |
| ASSERT_SAME_TYPE(typename std::atomic_ref<T>::value_type, T); |
| static_assert(!has_difference_type<std::atomic_ref<T>>); |
| } |
| } |
| |
| template <class T> |
| void test() { |
| // value_type and difference_type (except for primary template) |
| check_member_types<T>(); |
| |
| static_assert(std::is_nothrow_copy_constructible_v<std::atomic_ref<T>>); |
| |
| static_assert(!std::is_copy_assignable_v<std::atomic_ref<T>>); |
| |
| // explicit constructor |
| static_assert(!std::is_convertible_v<T, std::atomic_ref<T>>); |
| static_assert(std::is_constructible_v<std::atomic_ref<T>, T&>); |
| } |
| |
| void testall() { |
| // Primary template |
| struct Empty {}; |
| test<Empty>(); |
| struct Trivial { |
| int a; |
| float b; |
| }; |
| test<Trivial>(); |
| test<bool>(); |
| |
| // Partial specialization for pointer types |
| test<void*>(); |
| |
| // Specialization for integral types |
| // + character types |
| test<char>(); |
| test<char8_t>(); |
| test<char16_t>(); |
| test<char32_t>(); |
| test<wchar_t>(); |
| // + standard signed integer types |
| test<signed char>(); |
| test<short>(); |
| test<int>(); |
| test<long>(); |
| test<long long>(); |
| // + standard unsigned integer types |
| test<unsigned char>(); |
| test<unsigned short>(); |
| test<unsigned int>(); |
| test<unsigned long>(); |
| test<unsigned long long>(); |
| // + any other types needed by the typedefs in the header <cstdint> |
| test<int8_t>(); |
| test<int16_t>(); |
| test<int32_t>(); |
| test<int64_t>(); |
| test<int_fast8_t>(); |
| test<int_fast16_t>(); |
| test<int_fast32_t>(); |
| test<int_fast64_t>(); |
| test<int_least8_t>(); |
| test<int_least16_t>(); |
| test<int_least32_t>(); |
| test<int_least64_t>(); |
| test<intmax_t>(); |
| test<intptr_t>(); |
| test<uint8_t>(); |
| test<uint16_t>(); |
| test<uint32_t>(); |
| test<uint64_t>(); |
| test<uint_fast8_t>(); |
| test<uint_fast16_t>(); |
| test<uint_fast32_t>(); |
| test<uint_fast64_t>(); |
| test<uint_least8_t>(); |
| test<uint_least16_t>(); |
| test<uint_least32_t>(); |
| test<uint_least64_t>(); |
| test<uintmax_t>(); |
| test<uintptr_t>(); |
| |
| // Specialization for floating-point types |
| // + floating-point types |
| test<float>(); |
| test<double>(); |
| test<long double>(); |
| // + TODO extended floating-point types |
| } |