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 // UNSUPPORTED: gcc-10
11 // <optional>
12 
13 // template <class... Args> T& optional<T>::emplace(Args&&... args);
14 
15 #include <optional>
16 #include <type_traits>
17 #include <cassert>
18 #include <memory>
19 
20 #include "test_macros.h"
21 #include "archetypes.h"
22 
23 using std::optional;
24 
25 class X
26 {
27     int i_;
28     int j_ = 0;
29 public:
30     constexpr X() : i_(0) {}
31     constexpr X(int i) : i_(i) {}
32     constexpr X(int i, int j) : i_(i), j_(j) {}
33 
34     constexpr friend bool operator==(const X& x, const X& y)
35         {return x.i_ == y.i_ && x.j_ == y.j_;}
36 };
37 
38 class Y
39 {
40 public:
41     static bool dtor_called;
42     Y() = default;
43     Y(int) { TEST_THROW(6);}
44     ~Y() {dtor_called = true;}
45 };
46 
47 bool Y::dtor_called = false;
48 
49 template <class T>
50 constexpr bool test_one_arg() {
51     using Opt = std::optional<T>;
52     {
53         Opt opt;
54         auto & v = opt.emplace();
55         static_assert( std::is_same_v<T&, decltype(v)>, "" );
56         assert(static_cast<bool>(opt) == true);
57         assert(*opt == T(0));
58         assert(&v == &*opt);
59     }
60     {
61         Opt opt;
62         auto & v = opt.emplace(1);
63         static_assert( std::is_same_v<T&, decltype(v)>, "" );
64         assert(static_cast<bool>(opt) == true);
65         assert(*opt == T(1));
66         assert(&v == &*opt);
67     }
68     {
69         Opt opt(2);
70         auto & v = opt.emplace();
71         static_assert( std::is_same_v<T&, decltype(v)>, "" );
72         assert(static_cast<bool>(opt) == true);
73         assert(*opt == T(0));
74         assert(&v == &*opt);
75     }
76     {
77         Opt opt(2);
78         auto & v = opt.emplace(1);
79         static_assert( std::is_same_v<T&, decltype(v)>, "" );
80         assert(static_cast<bool>(opt) == true);
81         assert(*opt == T(1));
82         assert(&v == &*opt);
83     }
84     return true;
85 }
86 
87 
88 template <class T>
89 constexpr bool test_multi_arg()
90 {
91     test_one_arg<T>();
92     using Opt = std::optional<T>;
93     {
94         Opt opt;
95         auto &v = opt.emplace(101, 41);
96         static_assert( std::is_same_v<T&, decltype(v)>, "" );
97         assert(static_cast<bool>(opt) == true);
98         assert(   v == T(101, 41));
99         assert(*opt == T(101, 41));
100     }
101     {
102         Opt opt;
103         auto &v = opt.emplace({1, 2, 3, 4});
104         static_assert( std::is_same_v<T&, decltype(v)>, "" );
105         assert(static_cast<bool>(opt) == true);
106         assert(  v == T(4)); // T sets its value to the size of the init list
107         assert(*opt == T(4));
108     }
109     {
110         Opt opt;
111         auto &v = opt.emplace({1, 2, 3, 4, 5}, 6);
112         static_assert( std::is_same_v<T&, decltype(v)>, "" );
113         assert(static_cast<bool>(opt) == true);
114         assert(  v == T(5)); // T sets its value to the size of the init list
115         assert(*opt == T(5)); // T sets its value to the size of the init list
116     }
117     return true;
118 }
119 
120 template <class T>
121 void test_on_test_type() {
122 
123     T::reset();
124     optional<T> opt;
125     assert(T::alive == 0);
126     {
127         T::reset_constructors();
128         auto &v = opt.emplace();
129         static_assert( std::is_same_v<T&, decltype(v)>, "" );
130         assert(T::alive == 1);
131         assert(T::constructed == 1);
132         assert(T::default_constructed == 1);
133         assert(T::destroyed == 0);
134         assert(static_cast<bool>(opt) == true);
135         assert(*opt == T());
136         assert(&v == &*opt);
137     }
138     {
139         T::reset_constructors();
140         auto &v = opt.emplace();
141         static_assert( std::is_same_v<T&, decltype(v)>, "" );
142         assert(T::alive == 1);
143         assert(T::constructed == 1);
144         assert(T::default_constructed == 1);
145         assert(T::destroyed == 1);
146         assert(static_cast<bool>(opt) == true);
147         assert(*opt == T());
148         assert(&v == &*opt);
149     }
150     {
151         T::reset_constructors();
152         auto &v = opt.emplace(101);
153         static_assert( std::is_same_v<T&, decltype(v)>, "" );
154         assert(T::alive == 1);
155         assert(T::constructed == 1);
156         assert(T::value_constructed == 1);
157         assert(T::destroyed == 1);
158         assert(static_cast<bool>(opt) == true);
159         assert(*opt == T(101));
160         assert(&v == &*opt);
161     }
162     {
163         T::reset_constructors();
164         auto &v = opt.emplace(-10, 99);
165         static_assert( std::is_same_v<T&, decltype(v)>, "" );
166         assert(T::alive == 1);
167         assert(T::constructed == 1);
168         assert(T::value_constructed == 1);
169         assert(T::destroyed == 1);
170         assert(static_cast<bool>(opt) == true);
171         assert(*opt == T(-10, 99));
172         assert(&v == &*opt);
173     }
174     {
175         T::reset_constructors();
176         auto &v = opt.emplace(-10, 99);
177         static_assert( std::is_same_v<T&, decltype(v)>, "" );
178         assert(T::alive == 1);
179         assert(T::constructed == 1);
180         assert(T::value_constructed == 1);
181         assert(T::destroyed == 1);
182         assert(static_cast<bool>(opt) == true);
183         assert(*opt == T(-10, 99));
184         assert(&v == &*opt);
185     }
186     {
187         T::reset_constructors();
188         auto &v = opt.emplace({-10, 99, 42, 1});
189         static_assert( std::is_same_v<T&, decltype(v)>, "" );
190         assert(T::alive == 1);
191         assert(T::constructed == 1);
192         assert(T::value_constructed == 1);
193         assert(T::destroyed == 1);
194         assert(static_cast<bool>(opt) == true);
195         assert(*opt == T(4)); // size of the initializer list
196         assert(&v == &*opt);
197     }
198     {
199         T::reset_constructors();
200         auto &v = opt.emplace({-10, 99, 42, 1}, 42);
201         static_assert( std::is_same_v<T&, decltype(v)>, "" );
202         assert(T::alive == 1);
203         assert(T::constructed == 1);
204         assert(T::value_constructed == 1);
205         assert(T::destroyed == 1);
206         assert(static_cast<bool>(opt) == true);
207         assert(*opt == T(4)); // size of the initializer list
208         assert(&v == &*opt);
209     }
210 }
211 
212 constexpr bool test_empty_emplace()
213 {
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 
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