1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
12 // template <class U> optional<T>& operator=(U&& v);
15 #include <type_traits>
19 #include "test_macros.h"
20 #include "archetypes.h"
25 static int dtor_called
;
26 ThrowAssign() = default;
27 ThrowAssign(int) { TEST_THROW(42); }
28 ThrowAssign
& operator=(int) {
31 ~ThrowAssign() { ++dtor_called
; }
33 int ThrowAssign::dtor_called
= 0;
35 template <class T
, class Arg
= T
, bool Expect
= true>
36 void assert_assignable() {
37 static_assert(std::is_assignable
<optional
<T
>&, Arg
>::value
== Expect
, "");
38 static_assert(!std::is_assignable
<const optional
<T
>&, Arg
>::value
, "");
42 explicit MismatchType(int) {}
43 explicit MismatchType(char*) {}
44 explicit MismatchType(int*) = delete;
45 MismatchType
& operator=(int) { return *this; }
46 MismatchType
& operator=(int*) { return *this; }
47 MismatchType
& operator=(char*) = delete;
50 struct FromOptionalType
{
51 using Opt
= std::optional
<FromOptionalType
>;
52 FromOptionalType() = default;
53 FromOptionalType(FromOptionalType
const&) = delete;
54 template <class Dummy
= void>
55 constexpr FromOptionalType(Opt
&) { Dummy::BARK
; }
56 template <class Dummy
= void>
57 constexpr FromOptionalType
& operator=(Opt
&) { Dummy::BARK
; return *this; }
61 using I
= TestTypes::TestType
;
62 using E
= ExplicitTestTypes::TestType
;
63 assert_assignable
<int>();
64 assert_assignable
<int, int&>();
65 assert_assignable
<int, int const&>();
67 assert_assignable
<I
, I
const&>();
68 assert_assignable
<I
, I
&&>();
69 assert_assignable
<I
, int>();
70 assert_assignable
<I
, void*, false>();
72 assert_assignable
<E
, E
const&>();
73 assert_assignable
<E
, E
&&>();
74 assert_assignable
<E
, int>();
75 assert_assignable
<E
, void*, false>();
77 assert_assignable
<MismatchType
, int>();
78 assert_assignable
<MismatchType
, int*, false>();
79 assert_assignable
<MismatchType
, char*, false>();
80 // Type constructible from optional
81 assert_assignable
<FromOptionalType
, std::optional
<FromOptionalType
>&, false>();
84 void test_with_test_type()
86 using T
= TestTypes::TestType
;
91 assert(T::alive
== 1);
92 assert(T::constructed
== 1);
93 assert(T::value_constructed
== 1);
94 assert(T::assigned
== 0);
95 assert(T::destroyed
== 0);
96 assert(static_cast<bool>(opt
) == true);
101 T::reset_constructors();
103 assert(T::alive
== 1);
104 assert(T::constructed
== 0);
105 assert(T::assigned
== 1);
106 assert(T::value_assigned
== 1);
107 assert(T::destroyed
== 0);
108 assert(static_cast<bool>(opt
) == true);
109 assert(*opt
== T(3));
111 { // test default argument
113 T::reset_constructors();
115 assert(T::alive
== 1);
116 assert(T::constructed
== 2);
117 assert(T::value_constructed
== 1);
118 assert(T::move_constructed
== 1);
119 assert(T::assigned
== 0);
120 assert(T::destroyed
== 1);
121 assert(static_cast<bool>(opt
) == true);
122 assert(*opt
== T(1, 2));
124 { // test default argument
126 T::reset_constructors();
128 assert(T::alive
== 1);
129 assert(T::constructed
== 1);
130 assert(T::value_constructed
== 1);
131 assert(T::assigned
== 1);
132 assert(T::move_assigned
== 1);
133 assert(T::destroyed
== 1);
134 assert(static_cast<bool>(opt
) == true);
135 assert(*opt
== T(1, 2));
137 { // test default argument
139 T::reset_constructors();
141 assert(T::alive
== 1);
142 assert(T::constructed
== 2);
143 assert(T::value_constructed
== 1);
144 assert(T::move_constructed
== 1);
145 assert(T::assigned
== 0);
146 assert(T::destroyed
== 1);
147 assert(static_cast<bool>(opt
) == true);
148 assert(*opt
== T(1));
150 { // test default argument
152 T::reset_constructors();
154 assert(static_cast<bool>(opt
) == false);
155 assert(T::alive
== 0);
156 assert(T::constructed
== 0);
157 assert(T::assigned
== 0);
158 assert(T::destroyed
== 1);
162 template <class T
, class Value
= int>
163 void test_with_type() {
167 assert(static_cast<bool>(opt
) == true);
168 assert(*opt
== T(3));
171 optional
<T
> opt(Value(42));
173 assert(static_cast<bool>(opt
) == true);
174 assert(*opt
== T(3));
177 optional
<T
> opt(Value(42));
180 assert(static_cast<bool>(opt
) == true);
181 assert(*opt
== T(3));
183 { // test default argument
186 assert(static_cast<bool>(opt
) == true);
187 assert(*opt
== T(1));
189 { // test default argument
190 optional
<T
> opt(Value(42));
192 assert(static_cast<bool>(opt
) == false);
197 void test_with_type_multi() {
199 { // test default argument
202 assert(static_cast<bool>(opt
) == true);
203 assert(*opt
== T(1, 2));
205 { // test default argument
208 assert(static_cast<bool>(opt
) == true);
209 assert(*opt
== T(1, 2));
215 #ifndef TEST_HAS_NO_EXCEPTIONS
216 using T
= ThrowAssign
;
223 assert(static_cast<bool>(opt
) == false);
225 assert(T::dtor_called
== 0);
228 optional
<T
> opt(std::in_place
);
233 assert(static_cast<bool>(opt
) == true);
234 assert(T::dtor_called
== 0);
236 assert(T::dtor_called
== 1);
240 enum MyEnum
{ Zero
, One
, Two
, Three
, FortyTwo
= 42 };
242 using Fn
= void(*)();
244 // https://llvm.org/PR38638
246 constexpr T
pr38638(T v
)
254 int main(int, char**)
257 // Test with instrumented type
258 test_with_test_type();
259 // Test with various scalar types
260 test_with_type
<int>();
261 test_with_type
<MyEnum
, MyEnum
>();
262 test_with_type
<int, MyEnum
>();
263 test_with_type
<Fn
, Fn
>();
264 // Test types with multi argument constructors
265 test_with_type_multi
<ConstexprTestTypes::TestType
>();
266 test_with_type_multi
<TrivialTestTypes::TestType
>();
267 // Test move only types
269 optional
<std::unique_ptr
<int>> opt
;
270 opt
= std::unique_ptr
<int>(new int(3));
271 assert(static_cast<bool>(opt
) == true);
275 optional
<std::unique_ptr
<int>> opt(std::unique_ptr
<int>(new int(2)));
276 opt
= std::unique_ptr
<int>(new int(3));
277 assert(static_cast<bool>(opt
) == true);
282 static_assert(pr38638(3) == 5, "");