1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10
11 // <copyable-box>& operator=(<copyable-box> const&)
12
13 // ADDITIONAL_COMPILE_FLAGS: -Wno-self-assign-overloaded
14
15 #include <ranges>
16
17 #include <cassert>
18 #include <type_traits>
19 #include <utility> // in_place_t
20
21 #include "test_macros.h"
22 #include "types.h"
23
test()24 constexpr bool test() {
25 // Test the primary template
26 {
27 using Box = std::ranges::__movable_box<CopyConstructible>;
28 static_assert(std::is_copy_assignable_v<Box>);
29 static_assert(!std::is_nothrow_copy_assignable_v<Box>);
30
31 {
32 Box x(std::in_place, 5);
33 Box const y(std::in_place, 10);
34 Box& result = (x = y);
35
36 assert(&result == &x);
37 assert(x.__has_value());
38 assert(y.__has_value());
39 assert((*x).value == 10);
40 }
41 // check self-assignment
42 {
43 Box x(std::in_place, 5);
44 Box& result = (x = x);
45
46 assert(&result == &x);
47 assert(x.__has_value());
48 assert((*x).value == 5);
49 }
50 }
51
52 // Test optimization #1 for copy-assignment
53 {
54 using Box = std::ranges::__movable_box<Copyable>;
55 static_assert(std::is_copy_assignable_v<Box>);
56 static_assert(!std::is_nothrow_copy_assignable_v<Box>);
57
58 {
59 Box x(std::in_place, 5);
60 Box const y(std::in_place, 10);
61 Box& result = (x = y);
62
63 assert(&result == &x);
64 assert(x.__has_value());
65 assert(y.__has_value());
66 assert((*x).value == 10);
67 assert((*x).did_copy_assign);
68 }
69 // check self-assignment (should use the underlying type's assignment too)
70 {
71 Box x(std::in_place, 5);
72 Box& result = (x = x);
73
74 assert(&result == &x);
75 assert(x.__has_value());
76 assert((*x).value == 5);
77 assert((*x).did_copy_assign);
78 }
79 }
80
81 // Test optimization #2 for copy-assignment
82 {
83 using Box = std::ranges::__movable_box<NothrowCopyConstructible>;
84 static_assert(std::is_copy_assignable_v<Box>);
85 static_assert(std::is_nothrow_copy_assignable_v<Box>);
86
87 {
88 Box x(std::in_place, 5);
89 Box const y(std::in_place, 10);
90 Box& result = (x = y);
91
92 assert(&result == &x);
93 assert(x.__has_value());
94 assert(y.__has_value());
95 assert((*x).value == 10);
96 }
97 // check self-assignment
98 {
99 Box x(std::in_place, 5);
100 Box& result = (x = x);
101
102 assert(&result == &x);
103 assert(x.__has_value());
104 assert((*x).value == 5);
105 }
106 }
107
108 return true;
109 }
110
111 // Tests for the empty state. Those can't be constexpr, since they are only reached
112 // through throwing an exception.
113 #if !defined(TEST_HAS_NO_EXCEPTIONS)
test_empty_state()114 void test_empty_state() {
115 using Box = std::ranges::__movable_box<ThrowsOnCopy>;
116
117 // assign non-empty to empty
118 {
119 Box x = create_empty_box();
120 Box const y(std::in_place, 10);
121 Box& result = (x = y);
122
123 assert(&result == &x);
124 assert(x.__has_value());
125 assert(y.__has_value());
126 assert((*x).value == 10);
127 }
128 // assign empty to non-empty
129 {
130 Box x(std::in_place, 5);
131 Box const y = create_empty_box();
132 Box& result = (x = y);
133
134 assert(&result == &x);
135 assert(!x.__has_value());
136 assert(!y.__has_value());
137 }
138 // assign empty to empty
139 {
140 Box x = create_empty_box();
141 Box const y = create_empty_box();
142 Box& result = (x = y);
143
144 assert(&result == &x);
145 assert(!x.__has_value());
146 assert(!y.__has_value());
147 }
148 // check self-assignment in empty case
149 {
150 Box x = create_empty_box();
151 Box& result = (x = x);
152
153 assert(&result == &x);
154 assert(!x.__has_value());
155 }
156 }
157 #endif // !defined(TEST_HAS_NO_EXCEPTIONS)
158
main(int,char **)159 int main(int, char**) {
160 assert(test());
161 static_assert(test());
162
163 #if !defined(TEST_HAS_NO_EXCEPTIONS)
164 test_empty_state();
165 #endif
166
167 return 0;
168 }
169