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 31 X() { ++alive; } 32 X(X&&) 33 { 34 if (throw_now) 35 TEST_THROW(6); 36 ++alive; 37 } 38 39 X& operator=(X&&) 40 { 41 if (throw_now) 42 TEST_THROW(42); 43 return *this; 44 } 45 46 ~X() { assert(alive > 0); --alive; } 47 }; 48 49 struct Y {}; 50 51 bool X::throw_now = false; 52 int X::alive = 0; 53 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