1//
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
8// UNSUPPORTED: c++03, c++11, c++14, c++17
9// XFAIL: !has-64-bit-atomics
10
11// integral-type operator-=(integral-type) const noexcept;
12// floating-point-type operator-=(floating-point-type) const noexcept;
13// T* operator-=(difference_type) const noexcept;
14
15#include <atomic>
16#include <cassert>
17#include <concepts>
18#include <type_traits>
19#include <utility>
20
21#include "atomic_helpers.h"
22#include "test_helper.h"
23#include "test_macros.h"
24
25template <typename T>
26concept has_operator_minus_equals = requires { std::declval<T const>() -= std::declval<T>(); };
27
28template <typename T>
29struct TestDoesNotHaveOperatorMinusEquals {
30 void operator()() const { static_assert(!has_operator_minus_equals<std::atomic_ref<T>>); }
31};
32
33template <typename T>
34struct TestOperatorMinusEquals {
35 void operator()() const {
36 if constexpr (std::is_arithmetic_v<T>) {
37 T x(T(3));
38 std::atomic_ref<T> const a(x);
39
40 std::same_as<T> decltype(auto) y = (a -= T(2));
41 assert(y == T(1));
42 assert(x == T(1));
43 ASSERT_NOEXCEPT(a -= T(0));
44 } else if constexpr (std::is_pointer_v<T>) {
45 using U = std::remove_pointer_t<T>;
46 U t[9] = {};
47 T p{&t[3]};
48 std::atomic_ref<T> const a(p);
49
50 std::same_as<T> decltype(auto) y = (a -= 2);
51 assert(y == &t[1]);
52 assert(a == &t[1]);
53 ASSERT_NOEXCEPT(a -= 0);
54 } else {
55 static_assert(std::is_void_v<T>);
56 }
57
58 // memory_order::seq_cst
59 {
60 auto minus_equals = [](std::atomic_ref<T> const& x, T old_val, T new_val) { x -= (old_val - new_val); };
61 auto load = [](std::atomic_ref<T> const& x) { return x.load(); };
62 test_seq_cst<T>(minus_equals, load);
63 }
64 }
65};
66
67int main(int, char**) {
68 TestEachIntegralType<TestOperatorMinusEquals>()();
69
70 TestOperatorMinusEquals<float>()();
71 TestOperatorMinusEquals<double>()();
72
73 TestEachPointerType<TestOperatorMinusEquals>()();
74
75 TestDoesNotHaveOperatorMinusEquals<bool>()();
76 TestDoesNotHaveOperatorMinusEquals<UserAtomicType>()();
77 TestDoesNotHaveOperatorMinusEquals<LargeUserAtomicType>()();
78
79 return 0;
80}
81

source code of libcxx/test/std/atomics/atomics.ref/operator_minus_equals.pass.cpp