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