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
14 // optional<T>& operator=(optional<U>&& rhs);
21 #include <type_traits>
23 #include "test_macros.h"
24 #include "archetypes.h"
30 static bool throw_now
;
40 bool X::throw_now
= false;
46 Y1
& operator=(const Y1
&) = delete;
52 Y2(const int&) = delete;
53 Y2
& operator=(const int&) { return *this; }
56 struct B
{ virtual ~B() = default; };
57 class D
: public B
{};
61 struct AssignableFrom
{
62 static int type_constructed
;
63 static int type_assigned
;
64 static int int_constructed
;
65 static int int_assigned
;
68 type_constructed
= int_constructed
= 0;
69 type_assigned
= int_assigned
= 0;
72 AssignableFrom() = default;
74 explicit AssignableFrom(T
) { ++type_constructed
; }
75 AssignableFrom
& operator=(T
) { ++type_assigned
; return *this; }
77 AssignableFrom(int) { ++int_constructed
; }
78 AssignableFrom
& operator=(int) { ++int_assigned
; return *this; }
80 AssignableFrom(AssignableFrom
const&) = delete;
81 AssignableFrom
& operator=(AssignableFrom
const&) = delete;
84 template <class T
> int AssignableFrom
<T
>::type_constructed
= 0;
85 template <class T
> int AssignableFrom
<T
>::type_assigned
= 0;
86 template <class T
> int AssignableFrom
<T
>::int_constructed
= 0;
87 template <class T
> int AssignableFrom
<T
>::int_assigned
= 0;
89 void test_with_test_type() {
90 using T
= TestTypes::TestType
;
92 { // non-empty to empty
93 T::reset_constructors();
95 optional
<int> other(42);
96 opt
= std::move(other
);
97 assert(T::alive
== 1);
98 assert(T::constructed
== 1);
99 assert(T::value_constructed
== 1);
100 assert(T::assigned
== 0);
101 assert(T::destroyed
== 0);
102 assert(static_cast<bool>(other
) == true);
103 assert(*other
== 42);
104 assert(static_cast<bool>(opt
) == true);
105 assert(*opt
== T(42));
107 assert(T::alive
== 0);
108 { // non-empty to non-empty
109 optional
<T
> opt(101);
110 optional
<int> other(42);
111 T::reset_constructors();
112 opt
= std::move(other
);
113 assert(T::alive
== 1);
114 assert(T::constructed
== 0);
115 assert(T::assigned
== 1);
116 assert(T::value_assigned
== 1);
117 assert(T::destroyed
== 0);
118 assert(static_cast<bool>(other
) == true);
119 assert(*other
== 42);
120 assert(static_cast<bool>(opt
) == true);
121 assert(*opt
== T(42));
123 assert(T::alive
== 0);
124 { // empty to non-empty
125 optional
<T
> opt(101);
127 T::reset_constructors();
128 opt
= std::move(other
);
129 assert(T::alive
== 0);
130 assert(T::constructed
== 0);
131 assert(T::assigned
== 0);
132 assert(T::destroyed
== 1);
133 assert(static_cast<bool>(other
) == false);
134 assert(static_cast<bool>(opt
) == false);
136 assert(T::alive
== 0);
140 T::reset_constructors();
141 opt
= std::move(other
);
142 assert(T::alive
== 0);
143 assert(T::constructed
== 0);
144 assert(T::assigned
== 0);
145 assert(T::destroyed
== 0);
146 assert(static_cast<bool>(other
) == false);
147 assert(static_cast<bool>(opt
) == false);
149 assert(T::alive
== 0);
153 void test_ambiguous_assign() {
154 using OptInt
= std::optional
<int>;
156 using T
= AssignableFrom
<OptInt
&&>;
162 assert(T::type_constructed
== 1);
163 assert(T::type_assigned
== 0);
164 assert(T::int_constructed
== 0);
165 assert(T::int_assigned
== 0);
168 using Opt
= std::optional
<T
>;
169 static_assert(!std::is_assignable
<Opt
&, const OptInt
&&>::value
, "");
170 static_assert(!std::is_assignable
<Opt
&, const OptInt
&>::value
, "");
171 static_assert(!std::is_assignable
<Opt
&, OptInt
&>::value
, "");
175 using T
= AssignableFrom
<OptInt
const&&>;
181 assert(T::type_constructed
== 1);
182 assert(T::type_assigned
== 0);
183 assert(T::int_constructed
== 0);
184 assert(T::int_assigned
== 0);
191 assert(T::type_constructed
== 1);
192 assert(T::type_assigned
== 0);
193 assert(T::int_constructed
== 0);
194 assert(T::int_assigned
== 0);
197 using Opt
= std::optional
<T
>;
198 static_assert(std::is_assignable
<Opt
&, OptInt
&&>::value
, "");
199 static_assert(!std::is_assignable
<Opt
&, const OptInt
&>::value
, "");
200 static_assert(!std::is_assignable
<Opt
&, OptInt
&>::value
, "");
206 TEST_CONSTEXPR_CXX20
bool test()
210 optional
<short> opt2
;
211 opt
= std::move(opt2
);
212 assert(static_cast<bool>(opt2
) == false);
213 assert(static_cast<bool>(opt
) == static_cast<bool>(opt2
));
217 optional
<short> opt2(short{2});
218 opt
= std::move(opt2
);
219 assert(static_cast<bool>(opt2
) == true);
221 assert(static_cast<bool>(opt
) == static_cast<bool>(opt2
));
222 assert(*opt
== *opt2
);
225 optional
<int> opt(3);
226 optional
<short> opt2
;
227 opt
= std::move(opt2
);
228 assert(static_cast<bool>(opt2
) == false);
229 assert(static_cast<bool>(opt
) == static_cast<bool>(opt2
));
232 optional
<int> opt(3);
233 optional
<short> opt2(short{2});
234 opt
= std::move(opt2
);
235 assert(static_cast<bool>(opt2
) == true);
237 assert(static_cast<bool>(opt
) == static_cast<bool>(opt2
));
238 assert(*opt
== *opt2
);
241 enum class state_t
{ inactive
, constructed
, copy_assigned
, move_assigned
};
244 constexpr StateTracker(state_t
& s
)
247 *state_
= state_t::constructed
;
250 StateTracker(StateTracker
&&) = default;
251 StateTracker(StateTracker
const&) = default;
253 constexpr StateTracker
& operator=(StateTracker
&& other
) noexcept
255 *state_
= state_t::inactive
;
256 state_
= other
.state_
;
257 *state_
= state_t::move_assigned
;
258 other
.state_
= nullptr;
262 constexpr StateTracker
& operator=(StateTracker
const& other
) noexcept
264 *state_
= state_t::inactive
;
265 state_
= other
.state_
;
266 *state_
= state_t::copy_assigned
;
273 auto state
= std::array
{state_t::inactive
, state_t::inactive
};
274 auto opt1
= std::optional
<StateTracker
>(state
[0]);
275 assert(state
[0] == state_t::constructed
);
277 auto opt2
= std::optional
<StateTracker
>(state
[1]);
278 assert(state
[1] == state_t::constructed
);
280 opt1
= std::move(opt2
);
281 assert(state
[0] == state_t::inactive
);
282 assert(state
[1] == state_t::move_assigned
);
285 auto state
= std::array
{state_t::inactive
, state_t::inactive
};
286 auto opt1
= std::optional
<StateTracker
>(state
[0]);
287 assert(state
[0] == state_t::constructed
);
289 auto opt2
= std::optional
<StateTracker
>(state
[1]);
290 assert(state
[1] == state_t::constructed
);
293 assert(state
[0] == state_t::inactive
);
294 assert(state
[1] == state_t::copy_assigned
);
301 int main(int, char**)
303 #if TEST_STD_VER > 17
304 static_assert(test());
306 test_with_test_type();
307 test_ambiguous_assign();
310 optional
<std::unique_ptr
<B
>> opt
;
311 optional
<std::unique_ptr
<D
>> other(new D());
312 opt
= std::move(other
);
313 assert(static_cast<bool>(opt
) == true);
314 assert(static_cast<bool>(other
) == true);
315 assert(opt
->get() != nullptr);
316 assert(other
->get() == nullptr);
318 #ifndef TEST_HAS_NO_EXCEPTIONS
321 optional
<int> opt2(42);
322 assert(static_cast<bool>(opt2
) == true);
326 opt
= std::move(opt2
);
332 assert(static_cast<bool>(opt
) == false);