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