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 |
10 | // <optional> |
11 | |
12 | // template <class... Args> T& optional<T>::emplace(Args&&... args); |
13 | |
14 | #include <optional> |
15 | #include <type_traits> |
16 | #include <cassert> |
17 | #include <memory> |
18 | |
19 | #include "test_macros.h" |
20 | #include "archetypes.h" |
21 | |
22 | using std::optional; |
23 | |
24 | class X |
25 | { |
26 | int i_; |
27 | int j_ = 0; |
28 | public: |
29 | constexpr X() : i_(0) {} |
30 | constexpr X(int i) : i_(i) {} |
31 | constexpr X(int i, int j) : i_(i), j_(j) {} |
32 | |
33 | friend constexpr bool operator==(const X& x, const X& y) |
34 | {return x.i_ == y.i_ && x.j_ == y.j_;} |
35 | }; |
36 | |
37 | class Y |
38 | { |
39 | public: |
40 | static bool dtor_called; |
41 | Y() = default; |
42 | Y(int) { TEST_THROW(6);} |
43 | Y(const Y&) = default; |
44 | Y& operator=(const Y&) = default; |
45 | ~Y() {dtor_called = true;} |
46 | }; |
47 | |
48 | bool Y::dtor_called = false; |
49 | |
50 | template <class T> |
51 | constexpr bool test_one_arg() { |
52 | using Opt = std::optional<T>; |
53 | { |
54 | Opt opt; |
55 | auto & v = opt.emplace(); |
56 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
57 | assert(static_cast<bool>(opt) == true); |
58 | assert(*opt == T(0)); |
59 | assert(&v == &*opt); |
60 | } |
61 | { |
62 | Opt opt; |
63 | auto & v = opt.emplace(1); |
64 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
65 | assert(static_cast<bool>(opt) == true); |
66 | assert(*opt == T(1)); |
67 | assert(&v == &*opt); |
68 | } |
69 | { |
70 | Opt opt(2); |
71 | auto & v = opt.emplace(); |
72 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
73 | assert(static_cast<bool>(opt) == true); |
74 | assert(*opt == T(0)); |
75 | assert(&v == &*opt); |
76 | } |
77 | { |
78 | Opt opt(2); |
79 | auto & v = opt.emplace(1); |
80 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
81 | assert(static_cast<bool>(opt) == true); |
82 | assert(*opt == T(1)); |
83 | assert(&v == &*opt); |
84 | } |
85 | return true; |
86 | } |
87 | |
88 | |
89 | template <class T> |
90 | constexpr bool test_multi_arg() |
91 | { |
92 | test_one_arg<T>(); |
93 | using Opt = std::optional<T>; |
94 | { |
95 | Opt opt; |
96 | auto &v = opt.emplace(101, 41); |
97 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
98 | assert(static_cast<bool>(opt) == true); |
99 | assert( v == T(101, 41)); |
100 | assert(*opt == T(101, 41)); |
101 | } |
102 | { |
103 | Opt opt; |
104 | auto &v = opt.emplace({1, 2, 3, 4}); |
105 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
106 | assert(static_cast<bool>(opt) == true); |
107 | assert( v == T(4)); // T sets its value to the size of the init list |
108 | assert(*opt == T(4)); |
109 | } |
110 | { |
111 | Opt opt; |
112 | auto &v = opt.emplace({1, 2, 3, 4, 5}, 6); |
113 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
114 | assert(static_cast<bool>(opt) == true); |
115 | assert( v == T(5)); // T sets its value to the size of the init list |
116 | assert(*opt == T(5)); // T sets its value to the size of the init list |
117 | } |
118 | return true; |
119 | } |
120 | |
121 | template <class T> |
122 | void test_on_test_type() { |
123 | |
124 | T::reset(); |
125 | optional<T> opt; |
126 | assert(T::alive == 0); |
127 | { |
128 | T::reset_constructors(); |
129 | auto &v = opt.emplace(); |
130 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
131 | assert(T::alive == 1); |
132 | assert(T::constructed == 1); |
133 | assert(T::default_constructed == 1); |
134 | assert(T::destroyed == 0); |
135 | assert(static_cast<bool>(opt) == true); |
136 | assert(*opt == T()); |
137 | assert(&v == &*opt); |
138 | } |
139 | { |
140 | T::reset_constructors(); |
141 | auto &v = opt.emplace(); |
142 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
143 | assert(T::alive == 1); |
144 | assert(T::constructed == 1); |
145 | assert(T::default_constructed == 1); |
146 | assert(T::destroyed == 1); |
147 | assert(static_cast<bool>(opt) == true); |
148 | assert(*opt == T()); |
149 | assert(&v == &*opt); |
150 | } |
151 | { |
152 | T::reset_constructors(); |
153 | auto &v = opt.emplace(101); |
154 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
155 | assert(T::alive == 1); |
156 | assert(T::constructed == 1); |
157 | assert(T::value_constructed == 1); |
158 | assert(T::destroyed == 1); |
159 | assert(static_cast<bool>(opt) == true); |
160 | assert(*opt == T(101)); |
161 | assert(&v == &*opt); |
162 | } |
163 | { |
164 | T::reset_constructors(); |
165 | auto &v = opt.emplace(-10, 99); |
166 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
167 | assert(T::alive == 1); |
168 | assert(T::constructed == 1); |
169 | assert(T::value_constructed == 1); |
170 | assert(T::destroyed == 1); |
171 | assert(static_cast<bool>(opt) == true); |
172 | assert(*opt == T(-10, 99)); |
173 | assert(&v == &*opt); |
174 | } |
175 | { |
176 | T::reset_constructors(); |
177 | auto &v = opt.emplace(-10, 99); |
178 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
179 | assert(T::alive == 1); |
180 | assert(T::constructed == 1); |
181 | assert(T::value_constructed == 1); |
182 | assert(T::destroyed == 1); |
183 | assert(static_cast<bool>(opt) == true); |
184 | assert(*opt == T(-10, 99)); |
185 | assert(&v == &*opt); |
186 | } |
187 | { |
188 | T::reset_constructors(); |
189 | auto &v = opt.emplace({-10, 99, 42, 1}); |
190 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
191 | assert(T::alive == 1); |
192 | assert(T::constructed == 1); |
193 | assert(T::value_constructed == 1); |
194 | assert(T::destroyed == 1); |
195 | assert(static_cast<bool>(opt) == true); |
196 | assert(*opt == T(4)); // size of the initializer list |
197 | assert(&v == &*opt); |
198 | } |
199 | { |
200 | T::reset_constructors(); |
201 | auto &v = opt.emplace({-10, 99, 42, 1}, 42); |
202 | static_assert( std::is_same_v<T&, decltype(v)>, "" ); |
203 | assert(T::alive == 1); |
204 | assert(T::constructed == 1); |
205 | assert(T::value_constructed == 1); |
206 | assert(T::destroyed == 1); |
207 | assert(static_cast<bool>(opt) == true); |
208 | assert(*opt == T(4)); // size of the initializer list |
209 | assert(&v == &*opt); |
210 | } |
211 | } |
212 | |
213 | constexpr bool test_empty_emplace() |
214 | { |
215 | optional<const int> opt; |
216 | auto &v = opt.emplace(args: 42); |
217 | static_assert( std::is_same_v<const int&, decltype(v)>, "" ); |
218 | assert(*opt == 42); |
219 | assert( v == 42); |
220 | opt.emplace(); |
221 | assert(*opt == 0); |
222 | return true; |
223 | } |
224 | |
225 | int main(int, char**) |
226 | { |
227 | { |
228 | test_on_test_type<TestTypes::TestType>(); |
229 | test_on_test_type<ExplicitTestTypes::TestType>(); |
230 | } |
231 | { |
232 | using T = int; |
233 | test_one_arg<T>(); |
234 | test_one_arg<const T>(); |
235 | #if TEST_STD_VER > 17 |
236 | static_assert(test_one_arg<T>()); |
237 | static_assert(test_one_arg<const T>()); |
238 | #endif |
239 | } |
240 | { |
241 | using T = ConstexprTestTypes::TestType; |
242 | test_multi_arg<T>(); |
243 | #if TEST_STD_VER > 17 |
244 | static_assert(test_multi_arg<T>()); |
245 | #endif |
246 | } |
247 | { |
248 | using T = ExplicitConstexprTestTypes::TestType; |
249 | test_multi_arg<T>(); |
250 | #if TEST_STD_VER > 17 |
251 | static_assert(test_multi_arg<T>()); |
252 | #endif |
253 | } |
254 | { |
255 | using T = TrivialTestTypes::TestType; |
256 | test_multi_arg<T>(); |
257 | #if TEST_STD_VER > 17 |
258 | static_assert(test_multi_arg<T>()); |
259 | #endif |
260 | } |
261 | { |
262 | using T = ExplicitTrivialTestTypes::TestType; |
263 | test_multi_arg<T>(); |
264 | #if TEST_STD_VER > 17 |
265 | static_assert(test_multi_arg<T>()); |
266 | #endif |
267 | } |
268 | { |
269 | test_empty_emplace(); |
270 | #if TEST_STD_VER > 17 |
271 | static_assert(test_empty_emplace()); |
272 | #endif |
273 | } |
274 | #ifndef TEST_HAS_NO_EXCEPTIONS |
275 | Y::dtor_called = false; |
276 | { |
277 | Y y; |
278 | optional<Y> opt(y); |
279 | try |
280 | { |
281 | assert(static_cast<bool>(opt) == true); |
282 | assert(Y::dtor_called == false); |
283 | auto &v = opt.emplace(args: 1); |
284 | static_assert( std::is_same_v<Y&, decltype(v)>, "" ); |
285 | assert(false); |
286 | } |
287 | catch (int i) |
288 | { |
289 | assert(i == 6); |
290 | assert(static_cast<bool>(opt) == false); |
291 | assert(Y::dtor_called == true); |
292 | } |
293 | } |
294 | #endif |
295 | |
296 | return 0; |
297 | } |
298 | |