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 // template <class U> optional<T>& operator=(U&& v); 14 15 #include <optional> 16 #include <type_traits> 17 #include <cassert> 18 #include <memory> 19 20 #include "test_macros.h" 21 #include "archetypes.hpp" 22 23 using std::optional; 24 25 struct ThrowAssign { 26 static int dtor_called; 27 ThrowAssign() = default; 28 ThrowAssign(int) { TEST_THROW(42); } 29 ThrowAssign& operator=(int) { 30 TEST_THROW(42); 31 } 32 ~ThrowAssign() { ++dtor_called; } 33 }; 34 int ThrowAssign::dtor_called = 0; 35 36 template <class T, class Arg = T, bool Expect = true> 37 void assert_assignable() { 38 static_assert(std::is_assignable<optional<T>&, Arg>::value == Expect, ""); 39 static_assert(!std::is_assignable<const optional<T>&, Arg>::value, ""); 40 } 41 42 struct MismatchType { 43 explicit MismatchType(int) {} 44 explicit MismatchType(char*) {} 45 explicit MismatchType(int*) = delete; 46 MismatchType& operator=(int) { return *this; } 47 MismatchType& operator=(int*) { return *this; } 48 MismatchType& operator=(char*) = delete; 49 }; 50 51 struct FromOptionalType { 52 using Opt = std::optional<FromOptionalType>; 53 FromOptionalType() = default; 54 FromOptionalType(FromOptionalType const&) = delete; 55 template <class Dummy = void> 56 constexpr FromOptionalType(Opt&) { Dummy::BARK; } 57 template <class Dummy = void> 58 constexpr FromOptionalType& operator=(Opt&) { Dummy::BARK; return *this; } 59 }; 60 61 void test_sfinae() { 62 using I = TestTypes::TestType; 63 using E = ExplicitTestTypes::TestType; 64 assert_assignable<int>(); 65 assert_assignable<int, int&>(); 66 assert_assignable<int, int const&>(); 67 // Implicit test type 68 assert_assignable<I, I const&>(); 69 assert_assignable<I, I&&>(); 70 assert_assignable<I, int>(); 71 assert_assignable<I, void*, false>(); 72 // Explicit test type 73 assert_assignable<E, E const&>(); 74 assert_assignable<E, E &&>(); 75 assert_assignable<E, int>(); 76 assert_assignable<E, void*, false>(); 77 // Mismatch type 78 assert_assignable<MismatchType, int>(); 79 assert_assignable<MismatchType, int*, false>(); 80 assert_assignable<MismatchType, char*, false>(); 81 // Type constructible from optional 82 assert_assignable<FromOptionalType, std::optional<FromOptionalType>&, false>(); 83 } 84 85 void test_with_test_type() 86 { 87 using T = TestTypes::TestType; 88 T::reset(); 89 { // to empty 90 optional<T> opt; 91 opt = 3; 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>(opt) == true); 98 assert(*opt == T(3)); 99 } 100 { // to existing 101 optional<T> opt(42); 102 T::reset_constructors(); 103 opt = 3; 104 assert(T::alive == 1); 105 assert(T::constructed == 0); 106 assert(T::assigned == 1); 107 assert(T::value_assigned == 1); 108 assert(T::destroyed == 0); 109 assert(static_cast<bool>(opt) == true); 110 assert(*opt == T(3)); 111 } 112 { // test default argument 113 optional<T> opt; 114 T::reset_constructors(); 115 opt = {1, 2}; 116 assert(T::alive == 1); 117 assert(T::constructed == 2); 118 assert(T::value_constructed == 1); 119 assert(T::move_constructed == 1); 120 assert(T::assigned == 0); 121 assert(T::destroyed == 1); 122 assert(static_cast<bool>(opt) == true); 123 assert(*opt == T(1, 2)); 124 } 125 { // test default argument 126 optional<T> opt(42); 127 T::reset_constructors(); 128 opt = {1, 2}; 129 assert(T::alive == 1); 130 assert(T::constructed == 1); 131 assert(T::value_constructed == 1); 132 assert(T::assigned == 1); 133 assert(T::move_assigned == 1); 134 assert(T::destroyed == 1); 135 assert(static_cast<bool>(opt) == true); 136 assert(*opt == T(1, 2)); 137 } 138 { // test default argument 139 optional<T> opt; 140 T::reset_constructors(); 141 opt = {1}; 142 assert(T::alive == 1); 143 assert(T::constructed == 2); 144 assert(T::value_constructed == 1); 145 assert(T::move_constructed == 1); 146 assert(T::assigned == 0); 147 assert(T::destroyed == 1); 148 assert(static_cast<bool>(opt) == true); 149 assert(*opt == T(1)); 150 } 151 { // test default argument 152 optional<T> opt(42); 153 T::reset_constructors(); 154 opt = {}; 155 assert(static_cast<bool>(opt) == false); 156 assert(T::alive == 0); 157 assert(T::constructed == 0); 158 assert(T::assigned == 0); 159 assert(T::destroyed == 1); 160 } 161 } 162 163 template <class T, class Value = int> 164 void test_with_type() { 165 { // to empty 166 optional<T> opt; 167 opt = Value(3); 168 assert(static_cast<bool>(opt) == true); 169 assert(*opt == T(3)); 170 } 171 { // to existing 172 optional<T> opt(Value(42)); 173 opt = Value(3); 174 assert(static_cast<bool>(opt) == true); 175 assert(*opt == T(3)); 176 } 177 { // test const 178 optional<T> opt(Value(42)); 179 const T t(Value(3)); 180 opt = t; 181 assert(static_cast<bool>(opt) == true); 182 assert(*opt == T(3)); 183 } 184 { // test default argument 185 optional<T> opt; 186 opt = {Value(1)}; 187 assert(static_cast<bool>(opt) == true); 188 assert(*opt == T(1)); 189 } 190 { // test default argument 191 optional<T> opt(Value(42)); 192 opt = {}; 193 assert(static_cast<bool>(opt) == false); 194 } 195 } 196 197 template <class T> 198 void test_with_type_multi() { 199 test_with_type<T>(); 200 { // test default argument 201 optional<T> opt; 202 opt = {1, 2}; 203 assert(static_cast<bool>(opt) == true); 204 assert(*opt == T(1, 2)); 205 } 206 { // test default argument 207 optional<T> opt(42); 208 opt = {1, 2}; 209 assert(static_cast<bool>(opt) == true); 210 assert(*opt == T(1, 2)); 211 } 212 } 213 214 void test_throws() 215 { 216 #ifndef TEST_HAS_NO_EXCEPTIONS 217 using T = ThrowAssign; 218 { 219 using T = ThrowAssign; 220 optional<T> opt; 221 try { 222 opt = 42; 223 assert(false); 224 } catch (int) {} 225 assert(static_cast<bool>(opt) == false); 226 } 227 assert(T::dtor_called == 0); 228 { 229 T::dtor_called = 0; 230 optional<T> opt(std::in_place); 231 try { 232 opt = 42; 233 assert(false); 234 } catch (int) {} 235 assert(static_cast<bool>(opt) == true); 236 assert(T::dtor_called == 0); 237 } 238 assert(T::dtor_called == 1); 239 #endif 240 } 241 242 enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 }; 243 244 using Fn = void(*)(); 245 246 int main() 247 { 248 test_sfinae(); 249 // Test with instrumented type 250 test_with_test_type(); 251 // Test with various scalar types 252 test_with_type<int>(); 253 test_with_type<MyEnum, MyEnum>(); 254 test_with_type<int, MyEnum>(); 255 test_with_type<Fn, Fn>(); 256 // Test types with multi argument constructors 257 test_with_type_multi<ConstexprTestTypes::TestType>(); 258 test_with_type_multi<TrivialTestTypes::TestType>(); 259 // Test move only types 260 { 261 optional<std::unique_ptr<int>> opt; 262 opt = std::unique_ptr<int>(new int(3)); 263 assert(static_cast<bool>(opt) == true); 264 assert(**opt == 3); 265 } 266 { 267 optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2))); 268 opt = std::unique_ptr<int>(new int(3)); 269 assert(static_cast<bool>(opt) == true); 270 assert(**opt == 3); 271 } 272 test_throws(); 273 } 274