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 // optional<T>& operator=(optional<T>&& rhs)
14 // noexcept(is_nothrow_move_assignable<T>::value &&
15 // is_nothrow_move_constructible<T>::value);
16
17 #include <optional>
18 #include <type_traits>
19 #include <cassert>
20
21 #include "test_macros.h"
22 #include "archetypes.hpp"
23
24 using std::optional;
25
26 struct X
27 {
28 static bool throw_now;
29 static int alive;
30
XX31 X() { ++alive; }
XX32 X(X&&)
33 {
34 if (throw_now)
35 TEST_THROW(6);
36 ++alive;
37 }
38
operator =X39 X& operator=(X&&)
40 {
41 if (throw_now)
42 TEST_THROW(42);
43 return *this;
44 }
45
~XX46 ~X() { assert(alive > 0); --alive; }
47 };
48
49 struct Y {};
50
51 bool X::throw_now = false;
52 int X::alive = 0;
53
main()54 int main()
55 {
56 {
57 static_assert(std::is_nothrow_move_assignable<optional<int>>::value, "");
58 optional<int> opt;
59 constexpr optional<int> opt2;
60 opt = std::move(opt2);
61 static_assert(static_cast<bool>(opt2) == false, "");
62 assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
63 }
64 {
65 optional<int> opt;
66 constexpr optional<int> opt2(2);
67 opt = std::move(opt2);
68 static_assert(static_cast<bool>(opt2) == true, "");
69 static_assert(*opt2 == 2, "");
70 assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
71 assert(*opt == *opt2);
72 }
73 {
74 optional<int> opt(3);
75 constexpr optional<int> opt2;
76 opt = std::move(opt2);
77 static_assert(static_cast<bool>(opt2) == false, "");
78 assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
79 }
80 {
81 using T = TestTypes::TestType;
82 T::reset();
83 optional<T> opt(3);
84 optional<T> opt2;
85 assert(T::alive == 1);
86 opt = std::move(opt2);
87 assert(T::alive == 0);
88 assert(static_cast<bool>(opt2) == false);
89 assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
90 }
91 {
92 optional<int> opt(3);
93 constexpr optional<int> opt2(2);
94 opt = std::move(opt2);
95 static_assert(static_cast<bool>(opt2) == true, "");
96 static_assert(*opt2 == 2, "");
97 assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
98 assert(*opt == *opt2);
99 }
100 #ifndef TEST_HAS_NO_EXCEPTIONS
101 {
102 static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
103 X::alive = 0;
104 X::throw_now = false;
105 optional<X> opt;
106 optional<X> opt2(X{});
107 assert(X::alive == 1);
108 assert(static_cast<bool>(opt2) == true);
109 try
110 {
111 X::throw_now = true;
112 opt = std::move(opt2);
113 assert(false);
114 }
115 catch (int i)
116 {
117 assert(i == 6);
118 assert(static_cast<bool>(opt) == false);
119 }
120 assert(X::alive == 1);
121 }
122 assert(X::alive == 0);
123 {
124 static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
125 X::throw_now = false;
126 optional<X> opt(X{});
127 optional<X> opt2(X{});
128 assert(X::alive == 2);
129 assert(static_cast<bool>(opt2) == true);
130 try
131 {
132 X::throw_now = true;
133 opt = std::move(opt2);
134 assert(false);
135 }
136 catch (int i)
137 {
138 assert(i == 42);
139 assert(static_cast<bool>(opt) == true);
140 }
141 assert(X::alive == 2);
142 }
143 assert(X::alive == 0);
144 #endif // TEST_HAS_NO_EXCEPTIONS
145 {
146 static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, "");
147 }
148 {
149 struct ThrowsMove {
150 ThrowsMove() noexcept {}
151 ThrowsMove(ThrowsMove const&) noexcept {}
152 ThrowsMove(ThrowsMove &&) noexcept(false) {}
153 ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; }
154 ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; }
155 };
156 static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, "");
157 struct ThrowsMoveAssign {
158 ThrowsMoveAssign() noexcept {}
159 ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {}
160 ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {}
161 ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; }
162 ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; }
163 };
164 static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, "");
165 struct NoThrowMove {
166 NoThrowMove() noexcept(false) {}
167 NoThrowMove(NoThrowMove const&) noexcept(false) {}
168 NoThrowMove(NoThrowMove &&) noexcept {}
169 NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; }
170 NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; }
171 };
172 static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, "");
173 }
174 }
175