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