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