//===----------------------------------------------------------------------===//
//
// 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
}