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:
X()29 constexpr X() : i_(0) {}
X(int i)30 constexpr X(int i) : i_(i) {}
X(int i,int j)31 constexpr X(int i, int j) : i_(i), j_(j) {}
32
operator ==(const X & x,const X & y)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;
Y(int)42 Y(int) { TEST_THROW(6);}
43 Y(const Y&) = default;
44 Y& operator=(const Y&) = default;
~Y()45 ~Y() {dtor_called = true;}
46 };
47
48 bool Y::dtor_called = false;
49
50 template <class T>
test_one_arg()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>
test_multi_arg()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>
test_on_test_type()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
test_empty_emplace()213 TEST_CONSTEXPR_CXX20 bool test_empty_emplace() {
214 optional<const int> opt;
215 auto& v = opt.emplace(42);
216 static_assert(std::is_same_v<const int&, decltype(v)>, "");
217 assert(*opt == 42);
218 assert(v == 42);
219 opt.emplace();
220 assert(*opt == 0);
221 return true;
222 }
223
main(int,char **)224 int main(int, char**)
225 {
226 {
227 test_on_test_type<TestTypes::TestType>();
228 test_on_test_type<ExplicitTestTypes::TestType>();
229 }
230 {
231 using T = int;
232 test_one_arg<T>();
233 test_one_arg<const T>();
234 #if TEST_STD_VER > 17
235 static_assert(test_one_arg<T>());
236 static_assert(test_one_arg<const T>());
237 #endif
238 }
239 {
240 using T = ConstexprTestTypes::TestType;
241 test_multi_arg<T>();
242 #if TEST_STD_VER > 17
243 static_assert(test_multi_arg<T>());
244 #endif
245 }
246 {
247 using T = ExplicitConstexprTestTypes::TestType;
248 test_multi_arg<T>();
249 #if TEST_STD_VER > 17
250 static_assert(test_multi_arg<T>());
251 #endif
252 }
253 {
254 using T = TrivialTestTypes::TestType;
255 test_multi_arg<T>();
256 #if TEST_STD_VER > 17
257 static_assert(test_multi_arg<T>());
258 #endif
259 }
260 {
261 using T = ExplicitTrivialTestTypes::TestType;
262 test_multi_arg<T>();
263 #if TEST_STD_VER > 17
264 static_assert(test_multi_arg<T>());
265 #endif
266 }
267 {
268 test_empty_emplace();
269 #if TEST_STD_VER > 17
270 static_assert(test_empty_emplace());
271 #endif
272 }
273 #ifndef TEST_HAS_NO_EXCEPTIONS
274 Y::dtor_called = false;
275 {
276 Y y;
277 optional<Y> opt(y);
278 try
279 {
280 assert(static_cast<bool>(opt) == true);
281 assert(Y::dtor_called == false);
282 auto &v = opt.emplace(1);
283 static_assert( std::is_same_v<Y&, decltype(v)>, "" );
284 assert(false);
285 }
286 catch (int i)
287 {
288 assert(i == 6);
289 assert(static_cast<bool>(opt) == false);
290 assert(Y::dtor_called == true);
291 }
292 }
293 #endif
294
295 return 0;
296 }
297