1 //===----------------------------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // UNSUPPORTED: c++98, c++03, c++11, c++14
11 // <optional>
12
13 // template <class U> optional<T>& operator=(U&& v);
14
15 #include <optional>
16 #include <type_traits>
17 #include <cassert>
18 #include <memory>
19
20 #include "test_macros.h"
21 #include "archetypes.hpp"
22
23 using std::optional;
24
25 struct ThrowAssign {
26 static int dtor_called;
27 ThrowAssign() = default;
ThrowAssignThrowAssign28 ThrowAssign(int) { TEST_THROW(42); }
operator =ThrowAssign29 ThrowAssign& operator=(int) {
30 TEST_THROW(42);
31 }
~ThrowAssignThrowAssign32 ~ThrowAssign() { ++dtor_called; }
33 };
34 int ThrowAssign::dtor_called = 0;
35
36 template <class T, class Arg = T, bool Expect = true>
assert_assignable()37 void assert_assignable() {
38 static_assert(std::is_assignable<optional<T>&, Arg>::value == Expect, "");
39 static_assert(!std::is_assignable<const optional<T>&, Arg>::value, "");
40 }
41
42 struct MismatchType {
MismatchTypeMismatchType43 explicit MismatchType(int) {}
MismatchTypeMismatchType44 explicit MismatchType(char*) {}
45 explicit MismatchType(int*) = delete;
operator =MismatchType46 MismatchType& operator=(int) { return *this; }
operator =MismatchType47 MismatchType& operator=(int*) { return *this; }
48 MismatchType& operator=(char*) = delete;
49 };
50
51 struct FromOptionalType {
52 using Opt = std::optional<FromOptionalType>;
53 FromOptionalType() = default;
54 FromOptionalType(FromOptionalType const&) = delete;
55 template <class Dummy = void>
FromOptionalTypeFromOptionalType56 constexpr FromOptionalType(Opt&) { Dummy::BARK; }
57 template <class Dummy = void>
operator =FromOptionalType58 constexpr FromOptionalType& operator=(Opt&) { Dummy::BARK; return *this; }
59 };
60
test_sfinae()61 void test_sfinae() {
62 using I = TestTypes::TestType;
63 using E = ExplicitTestTypes::TestType;
64 assert_assignable<int>();
65 assert_assignable<int, int&>();
66 assert_assignable<int, int const&>();
67 // Implicit test type
68 assert_assignable<I, I const&>();
69 assert_assignable<I, I&&>();
70 assert_assignable<I, int>();
71 assert_assignable<I, void*, false>();
72 // Explicit test type
73 assert_assignable<E, E const&>();
74 assert_assignable<E, E &&>();
75 assert_assignable<E, int>();
76 assert_assignable<E, void*, false>();
77 // Mismatch type
78 assert_assignable<MismatchType, int>();
79 assert_assignable<MismatchType, int*, false>();
80 assert_assignable<MismatchType, char*, false>();
81 // Type constructible from optional
82 assert_assignable<FromOptionalType, std::optional<FromOptionalType>&, false>();
83 }
84
test_with_test_type()85 void test_with_test_type()
86 {
87 using T = TestTypes::TestType;
88 T::reset();
89 { // to empty
90 optional<T> opt;
91 opt = 3;
92 assert(T::alive == 1);
93 assert(T::constructed == 1);
94 assert(T::value_constructed == 1);
95 assert(T::assigned == 0);
96 assert(T::destroyed == 0);
97 assert(static_cast<bool>(opt) == true);
98 assert(*opt == T(3));
99 }
100 { // to existing
101 optional<T> opt(42);
102 T::reset_constructors();
103 opt = 3;
104 assert(T::alive == 1);
105 assert(T::constructed == 0);
106 assert(T::assigned == 1);
107 assert(T::value_assigned == 1);
108 assert(T::destroyed == 0);
109 assert(static_cast<bool>(opt) == true);
110 assert(*opt == T(3));
111 }
112 { // test default argument
113 optional<T> opt;
114 T::reset_constructors();
115 opt = {1, 2};
116 assert(T::alive == 1);
117 assert(T::constructed == 2);
118 assert(T::value_constructed == 1);
119 assert(T::move_constructed == 1);
120 assert(T::assigned == 0);
121 assert(T::destroyed == 1);
122 assert(static_cast<bool>(opt) == true);
123 assert(*opt == T(1, 2));
124 }
125 { // test default argument
126 optional<T> opt(42);
127 T::reset_constructors();
128 opt = {1, 2};
129 assert(T::alive == 1);
130 assert(T::constructed == 1);
131 assert(T::value_constructed == 1);
132 assert(T::assigned == 1);
133 assert(T::move_assigned == 1);
134 assert(T::destroyed == 1);
135 assert(static_cast<bool>(opt) == true);
136 assert(*opt == T(1, 2));
137 }
138 { // test default argument
139 optional<T> opt;
140 T::reset_constructors();
141 opt = {1};
142 assert(T::alive == 1);
143 assert(T::constructed == 2);
144 assert(T::value_constructed == 1);
145 assert(T::move_constructed == 1);
146 assert(T::assigned == 0);
147 assert(T::destroyed == 1);
148 assert(static_cast<bool>(opt) == true);
149 assert(*opt == T(1));
150 }
151 { // test default argument
152 optional<T> opt(42);
153 T::reset_constructors();
154 opt = {};
155 assert(static_cast<bool>(opt) == false);
156 assert(T::alive == 0);
157 assert(T::constructed == 0);
158 assert(T::assigned == 0);
159 assert(T::destroyed == 1);
160 }
161 }
162
163 template <class T, class Value = int>
test_with_type()164 void test_with_type() {
165 { // to empty
166 optional<T> opt;
167 opt = Value(3);
168 assert(static_cast<bool>(opt) == true);
169 assert(*opt == T(3));
170 }
171 { // to existing
172 optional<T> opt(Value(42));
173 opt = Value(3);
174 assert(static_cast<bool>(opt) == true);
175 assert(*opt == T(3));
176 }
177 { // test const
178 optional<T> opt(Value(42));
179 const T t(Value(3));
180 opt = t;
181 assert(static_cast<bool>(opt) == true);
182 assert(*opt == T(3));
183 }
184 { // test default argument
185 optional<T> opt;
186 opt = {Value(1)};
187 assert(static_cast<bool>(opt) == true);
188 assert(*opt == T(1));
189 }
190 { // test default argument
191 optional<T> opt(Value(42));
192 opt = {};
193 assert(static_cast<bool>(opt) == false);
194 }
195 }
196
197 template <class T>
test_with_type_multi()198 void test_with_type_multi() {
199 test_with_type<T>();
200 { // test default argument
201 optional<T> opt;
202 opt = {1, 2};
203 assert(static_cast<bool>(opt) == true);
204 assert(*opt == T(1, 2));
205 }
206 { // test default argument
207 optional<T> opt(42);
208 opt = {1, 2};
209 assert(static_cast<bool>(opt) == true);
210 assert(*opt == T(1, 2));
211 }
212 }
213
test_throws()214 void test_throws()
215 {
216 #ifndef TEST_HAS_NO_EXCEPTIONS
217 using T = ThrowAssign;
218 {
219 optional<T> opt;
220 try {
221 opt = 42;
222 assert(false);
223 } catch (int) {}
224 assert(static_cast<bool>(opt) == false);
225 }
226 assert(T::dtor_called == 0);
227 {
228 T::dtor_called = 0;
229 optional<T> opt(std::in_place);
230 try {
231 opt = 42;
232 assert(false);
233 } catch (int) {}
234 assert(static_cast<bool>(opt) == true);
235 assert(T::dtor_called == 0);
236 }
237 assert(T::dtor_called == 1);
238 #endif
239 }
240
241 enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 };
242
243 using Fn = void(*)();
244
main()245 int main()
246 {
247 test_sfinae();
248 // Test with instrumented type
249 test_with_test_type();
250 // Test with various scalar types
251 test_with_type<int>();
252 test_with_type<MyEnum, MyEnum>();
253 test_with_type<int, MyEnum>();
254 test_with_type<Fn, Fn>();
255 // Test types with multi argument constructors
256 test_with_type_multi<ConstexprTestTypes::TestType>();
257 test_with_type_multi<TrivialTestTypes::TestType>();
258 // Test move only types
259 {
260 optional<std::unique_ptr<int>> opt;
261 opt = std::unique_ptr<int>(new int(3));
262 assert(static_cast<bool>(opt) == true);
263 assert(**opt == 3);
264 }
265 {
266 optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2)));
267 opt = std::unique_ptr<int>(new int(3));
268 assert(static_cast<bool>(opt) == true);
269 assert(**opt == 3);
270 }
271 test_throws();
272 }
273