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