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++98, 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     X() : i_(0) {}
X(int i)30     X(int i) : i_(i) {}
X(int i,int j)31     X(int i, int j) : i_(i), j_(j) {}
32 
operator ==(const X & x,const X & y)33     friend 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 void 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 }
84 
85 
86 template <class T>
test_multi_arg()87 void test_multi_arg()
88 {
89     test_one_arg<T>();
90     using Opt = std::optional<T>;
91     {
92         Opt opt;
93         auto &v = opt.emplace(101, 41);
94         static_assert( std::is_same_v<T&, decltype(v)>, "" );
95         assert(static_cast<bool>(opt) == true);
96         assert(   v == T(101, 41));
97         assert(*opt == T(101, 41));
98     }
99     {
100         Opt opt;
101         auto &v = opt.emplace({1, 2, 3, 4});
102         static_assert( std::is_same_v<T&, decltype(v)>, "" );
103         assert(static_cast<bool>(opt) == true);
104         assert(  v == T(4)); // T sets its value to the size of the init list
105         assert(*opt == T(4));
106     }
107     {
108         Opt opt;
109         auto &v = opt.emplace({1, 2, 3, 4, 5}, 6);
110         static_assert( std::is_same_v<T&, decltype(v)>, "" );
111         assert(static_cast<bool>(opt) == true);
112         assert(  v == T(5)); // T sets its value to the size of the init list
113         assert(*opt == T(5)); // T sets its value to the size of the init list
114     }
115 }
116 
117 template <class T>
test_on_test_type()118 void test_on_test_type() {
119 
120     T::reset();
121     optional<T> opt;
122     assert(T::alive == 0);
123     {
124         T::reset_constructors();
125         auto &v = opt.emplace();
126         static_assert( std::is_same_v<T&, decltype(v)>, "" );
127         assert(T::alive == 1);
128         assert(T::constructed == 1);
129         assert(T::default_constructed == 1);
130         assert(T::destroyed == 0);
131         assert(static_cast<bool>(opt) == true);
132         assert(*opt == T());
133         assert(&v == &*opt);
134     }
135     {
136         T::reset_constructors();
137         auto &v = opt.emplace();
138         static_assert( std::is_same_v<T&, decltype(v)>, "" );
139         assert(T::alive == 1);
140         assert(T::constructed == 1);
141         assert(T::default_constructed == 1);
142         assert(T::destroyed == 1);
143         assert(static_cast<bool>(opt) == true);
144         assert(*opt == T());
145         assert(&v == &*opt);
146     }
147     {
148         T::reset_constructors();
149         auto &v = opt.emplace(101);
150         static_assert( std::is_same_v<T&, decltype(v)>, "" );
151         assert(T::alive == 1);
152         assert(T::constructed == 1);
153         assert(T::value_constructed == 1);
154         assert(T::destroyed == 1);
155         assert(static_cast<bool>(opt) == true);
156         assert(*opt == T(101));
157         assert(&v == &*opt);
158     }
159     {
160         T::reset_constructors();
161         auto &v = opt.emplace(-10, 99);
162         static_assert( std::is_same_v<T&, decltype(v)>, "" );
163         assert(T::alive == 1);
164         assert(T::constructed == 1);
165         assert(T::value_constructed == 1);
166         assert(T::destroyed == 1);
167         assert(static_cast<bool>(opt) == true);
168         assert(*opt == T(-10, 99));
169         assert(&v == &*opt);
170     }
171     {
172         T::reset_constructors();
173         auto &v = opt.emplace(-10, 99);
174         static_assert( std::is_same_v<T&, decltype(v)>, "" );
175         assert(T::alive == 1);
176         assert(T::constructed == 1);
177         assert(T::value_constructed == 1);
178         assert(T::destroyed == 1);
179         assert(static_cast<bool>(opt) == true);
180         assert(*opt == T(-10, 99));
181         assert(&v == &*opt);
182     }
183     {
184         T::reset_constructors();
185         auto &v = opt.emplace({-10, 99, 42, 1});
186         static_assert( std::is_same_v<T&, decltype(v)>, "" );
187         assert(T::alive == 1);
188         assert(T::constructed == 1);
189         assert(T::value_constructed == 1);
190         assert(T::destroyed == 1);
191         assert(static_cast<bool>(opt) == true);
192         assert(*opt == T(4)); // size of the initializer list
193         assert(&v == &*opt);
194     }
195     {
196         T::reset_constructors();
197         auto &v = opt.emplace({-10, 99, 42, 1}, 42);
198         static_assert( std::is_same_v<T&, decltype(v)>, "" );
199         assert(T::alive == 1);
200         assert(T::constructed == 1);
201         assert(T::value_constructed == 1);
202         assert(T::destroyed == 1);
203         assert(static_cast<bool>(opt) == true);
204         assert(*opt == T(4)); // size of the initializer list
205         assert(&v == &*opt);
206     }
207 }
208 
209 
210 
main(int,char **)211 int main(int, char**)
212 {
213     {
214         test_on_test_type<TestTypes::TestType>();
215         test_on_test_type<ExplicitTestTypes::TestType>();
216     }
217     {
218         using T = int;
219         test_one_arg<T>();
220         test_one_arg<const T>();
221     }
222     {
223         using T = ConstexprTestTypes::TestType;
224         test_multi_arg<T>();
225     }
226     {
227         using T = ExplicitConstexprTestTypes::TestType;
228         test_multi_arg<T>();
229     }
230     {
231         using T = TrivialTestTypes::TestType;
232         test_multi_arg<T>();
233     }
234     {
235         using T = ExplicitTrivialTestTypes::TestType;
236         test_multi_arg<T>();
237     }
238     {
239         optional<const int> opt;
240         auto &v = opt.emplace(42);
241         static_assert( std::is_same_v<const int&, decltype(v)>, "" );
242         assert(*opt == 42);
243         assert(   v == 42);
244         opt.emplace();
245         assert(*opt == 0);
246     }
247 #ifndef TEST_HAS_NO_EXCEPTIONS
248     Y::dtor_called = false;
249     {
250         Y y;
251         optional<Y> opt(y);
252         try
253         {
254             assert(static_cast<bool>(opt) == true);
255             assert(Y::dtor_called == false);
256             auto &v = opt.emplace(1);
257             static_assert( std::is_same_v<Y&, decltype(v)>, "" );
258             assert(false);
259         }
260         catch (int i)
261         {
262             assert(i == 6);
263             assert(static_cast<bool>(opt) == false);
264             assert(Y::dtor_called == true);
265         }
266     }
267 #endif
268 
269   return 0;
270 }
271