move.pass.cpp (6277B)
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); // constexpr in C++20 16 17 #include <optional> 18 #include <cassert> 19 #include <type_traits> 20 #include <utility> 21 22 #include "test_macros.h" 23 #include "archetypes.hpp" 24 25 using std::optional; 26 27 struct X 28 { 29 static bool throw_now; 30 static int alive; 31 32 X() { ++alive; } 33 X(X&&) 34 { 35 if (throw_now) 36 TEST_THROW(6); 37 ++alive; 38 } 39 40 X& operator=(X&&) 41 { 42 if (throw_now) 43 TEST_THROW(42); 44 return *this; 45 } 46 47 ~X() { assert(alive > 0); --alive; } 48 }; 49 50 struct Y {}; 51 52 bool X::throw_now = false; 53 int X::alive = 0; 54 55 56 template <class Tp> 57 constexpr bool assign_empty(optional<Tp>&& lhs) { 58 optional<Tp> rhs; 59 lhs = std::move(rhs); 60 return !lhs.has_value() && !rhs.has_value(); 61 } 62 63 template <class Tp> 64 constexpr bool assign_value(optional<Tp>&& lhs) { 65 optional<Tp> rhs(101); 66 lhs = std::move(rhs); 67 return lhs.has_value() && rhs.has_value() && *lhs == Tp{101}; 68 } 69 70 int main() 71 { 72 { 73 static_assert(std::is_nothrow_move_assignable<optional<int>>::value, ""); 74 optional<int> opt; 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 optional<int> opt; 82 constexpr optional<int> opt2(2); 83 opt = std::move(opt2); 84 static_assert(static_cast<bool>(opt2) == true, ""); 85 static_assert(*opt2 == 2, ""); 86 assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); 87 assert(*opt == *opt2); 88 } 89 { 90 optional<int> opt(3); 91 constexpr optional<int> opt2; 92 opt = std::move(opt2); 93 static_assert(static_cast<bool>(opt2) == false, ""); 94 assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); 95 } 96 { 97 using T = TestTypes::TestType; 98 T::reset(); 99 optional<T> opt(3); 100 optional<T> opt2; 101 assert(T::alive == 1); 102 opt = std::move(opt2); 103 assert(T::alive == 0); 104 assert(static_cast<bool>(opt2) == false); 105 assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); 106 } 107 { 108 optional<int> opt(3); 109 constexpr optional<int> opt2(2); 110 opt = std::move(opt2); 111 static_assert(static_cast<bool>(opt2) == true, ""); 112 static_assert(*opt2 == 2, ""); 113 assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); 114 assert(*opt == *opt2); 115 } 116 { 117 using O = optional<int>; 118 #if TEST_STD_VER > 17 119 LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); 120 LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); 121 #endif 122 assert(assign_empty(O{42})); 123 assert(assign_value(O{42})); 124 } 125 { 126 using O = optional<TrivialTestTypes::TestType>; 127 #if TEST_STD_VER > 17 128 LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); 129 LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); 130 #endif 131 assert(assign_empty(O{42})); 132 assert(assign_value(O{42})); 133 } 134 #ifndef TEST_HAS_NO_EXCEPTIONS 135 { 136 static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, ""); 137 X::alive = 0; 138 X::throw_now = false; 139 optional<X> opt; 140 optional<X> opt2(X{}); 141 assert(X::alive == 1); 142 assert(static_cast<bool>(opt2) == true); 143 try 144 { 145 X::throw_now = true; 146 opt = std::move(opt2); 147 assert(false); 148 } 149 catch (int i) 150 { 151 assert(i == 6); 152 assert(static_cast<bool>(opt) == false); 153 } 154 assert(X::alive == 1); 155 } 156 assert(X::alive == 0); 157 { 158 static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, ""); 159 X::throw_now = false; 160 optional<X> opt(X{}); 161 optional<X> opt2(X{}); 162 assert(X::alive == 2); 163 assert(static_cast<bool>(opt2) == true); 164 try 165 { 166 X::throw_now = true; 167 opt = std::move(opt2); 168 assert(false); 169 } 170 catch (int i) 171 { 172 assert(i == 42); 173 assert(static_cast<bool>(opt) == true); 174 } 175 assert(X::alive == 2); 176 } 177 assert(X::alive == 0); 178 #endif // TEST_HAS_NO_EXCEPTIONS 179 { 180 static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, ""); 181 } 182 { 183 struct ThrowsMove { 184 ThrowsMove() noexcept {} 185 ThrowsMove(ThrowsMove const&) noexcept {} 186 ThrowsMove(ThrowsMove &&) noexcept(false) {} 187 ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; } 188 ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; } 189 }; 190 static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, ""); 191 struct ThrowsMoveAssign { 192 ThrowsMoveAssign() noexcept {} 193 ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {} 194 ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {} 195 ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; } 196 ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; } 197 }; 198 static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, ""); 199 struct NoThrowMove { 200 NoThrowMove() noexcept(false) {} 201 NoThrowMove(NoThrowMove const&) noexcept(false) {} 202 NoThrowMove(NoThrowMove &&) noexcept {} 203 NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; } 204 NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; } 205 }; 206 static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, ""); 207 } 208 }