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 // From LWG2451: 14 // template<class U> 15 // optional<T>& operator=(const optional<U>& rhs); 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 30 X() = default; 31 X(int) 32 { 33 if (throw_now) 34 TEST_THROW(6); 35 } 36 }; 37 38 bool X::throw_now = false; 39 40 struct Y1 41 { 42 Y1() = default; 43 Y1(const int&) {} 44 Y1& operator=(const Y1&) = delete; 45 }; 46 47 struct Y2 48 { 49 Y2() = default; 50 Y2(const int&) = delete; 51 Y2& operator=(const int&) { return *this; } 52 }; 53 54 template <class T> 55 struct AssignableFrom { 56 static int type_constructed; 57 static int type_assigned; 58 static int int_constructed; 59 static int int_assigned; 60 61 static void reset() { 62 type_constructed = int_constructed = 0; 63 type_assigned = int_assigned = 0; 64 } 65 66 AssignableFrom() = default; 67 68 explicit AssignableFrom(T) { ++type_constructed; } 69 AssignableFrom& operator=(T) { ++type_assigned; return *this; } 70 71 AssignableFrom(int) { ++int_constructed; } 72 AssignableFrom& operator=(int) { ++int_assigned; return *this; } 73 private: 74 AssignableFrom(AssignableFrom const&) = delete; 75 AssignableFrom& operator=(AssignableFrom const&) = delete; 76 }; 77 78 template <class T> int AssignableFrom<T>::type_constructed = 0; 79 template <class T> int AssignableFrom<T>::type_assigned = 0; 80 template <class T> int AssignableFrom<T>::int_constructed = 0; 81 template <class T> int AssignableFrom<T>::int_assigned = 0; 82 83 84 void test_with_test_type() { 85 using T = TestTypes::TestType; 86 T::reset(); 87 { // non-empty to empty 88 T::reset_constructors(); 89 optional<T> opt; 90 const optional<int> other(42); 91 opt = other; 92 assert(T::alive == 1); 93 assert(T::constructed == 1); 94 assert(T::value_constructed == 1); 95 assert(T::assigned == 0); 96 assert(T::destroyed == 0); 97 assert(static_cast<bool>(other) == true); 98 assert(*other == 42); 99 assert(static_cast<bool>(opt) == true); 100 assert(*opt == T(42)); 101 } 102 assert(T::alive == 0); 103 { // non-empty to non-empty 104 optional<T> opt(101); 105 const optional<int> other(42); 106 T::reset_constructors(); 107 opt = other; 108 assert(T::alive == 1); 109 assert(T::constructed == 0); 110 assert(T::assigned == 1); 111 assert(T::value_assigned == 1); 112 assert(T::destroyed == 0); 113 assert(static_cast<bool>(other) == true); 114 assert(*other == 42); 115 assert(static_cast<bool>(opt) == true); 116 assert(*opt == T(42)); 117 } 118 assert(T::alive == 0); 119 { // empty to non-empty 120 optional<T> opt(101); 121 const optional<int> other; 122 T::reset_constructors(); 123 opt = other; 124 assert(T::alive == 0); 125 assert(T::constructed == 0); 126 assert(T::assigned == 0); 127 assert(T::destroyed == 1); 128 assert(static_cast<bool>(other) == false); 129 assert(static_cast<bool>(opt) == false); 130 } 131 assert(T::alive == 0); 132 { // empty to empty 133 optional<T> opt; 134 const optional<int> other; 135 T::reset_constructors(); 136 opt = other; 137 assert(T::alive == 0); 138 assert(T::constructed == 0); 139 assert(T::assigned == 0); 140 assert(T::destroyed == 0); 141 assert(static_cast<bool>(other) == false); 142 assert(static_cast<bool>(opt) == false); 143 } 144 assert(T::alive == 0); 145 } 146 147 void test_ambigious_assign() { 148 using OptInt = std::optional<int>; 149 { 150 using T = AssignableFrom<OptInt const&>; 151 const OptInt a(42); 152 T::reset(); 153 { 154 std::optional<T> t; 155 t = a; 156 assert(T::type_constructed == 1); 157 assert(T::type_assigned == 0); 158 assert(T::int_constructed == 0); 159 assert(T::int_assigned == 0); 160 } 161 T::reset(); 162 { 163 std::optional<T> t(42); 164 t = a; 165 assert(T::type_constructed == 0); 166 assert(T::type_assigned == 1); 167 assert(T::int_constructed == 1); 168 assert(T::int_assigned == 0); 169 } 170 T::reset(); 171 { 172 std::optional<T> t(42); 173 t = std::move(a); 174 assert(T::type_constructed == 0); 175 assert(T::type_assigned == 1); 176 assert(T::int_constructed == 1); 177 assert(T::int_assigned == 0); 178 } 179 } 180 { 181 using T = AssignableFrom<OptInt&>; 182 OptInt a(42); 183 T::reset(); 184 { 185 std::optional<T> t; 186 t = a; 187 assert(T::type_constructed == 1); 188 assert(T::type_assigned == 0); 189 assert(T::int_constructed == 0); 190 assert(T::int_assigned == 0); 191 } 192 { 193 using Opt = std::optional<T>; 194 static_assert(!std::is_assignable_v<Opt&, OptInt const&>, ""); 195 } 196 } 197 } 198 199 200 int main() 201 { 202 test_with_test_type(); 203 test_ambigious_assign(); 204 { 205 optional<int> opt; 206 constexpr optional<short> opt2; 207 opt = opt2; 208 static_assert(static_cast<bool>(opt2) == false, ""); 209 assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); 210 } 211 { 212 optional<int> opt; 213 constexpr optional<short> opt2(short{2}); 214 opt = opt2; 215 static_assert(static_cast<bool>(opt2) == true, ""); 216 static_assert(*opt2 == 2, ""); 217 assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); 218 assert(*opt == *opt2); 219 } 220 { 221 optional<int> opt(3); 222 constexpr optional<short> opt2; 223 opt = opt2; 224 static_assert(static_cast<bool>(opt2) == false, ""); 225 assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); 226 } 227 { 228 optional<int> opt(3); 229 constexpr optional<short> opt2(short{2}); 230 opt = opt2; 231 static_assert(static_cast<bool>(opt2) == true, ""); 232 static_assert(*opt2 == 2, ""); 233 assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); 234 assert(*opt == *opt2); 235 } 236 #ifndef TEST_HAS_NO_EXCEPTIONS 237 { 238 optional<X> opt; 239 optional<int> opt2(42); 240 assert(static_cast<bool>(opt2) == true); 241 try 242 { 243 X::throw_now = true; 244 opt = opt2; 245 assert(false); 246 } 247 catch (int i) 248 { 249 assert(i == 6); 250 assert(static_cast<bool>(opt) == false); 251 } 252 } 253 #endif 254 } 255