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 void test_sfinae() { 52 using I = TestTypes::TestType; 53 using E = ExplicitTestTypes::TestType; 54 assert_assignable<int>(); 55 assert_assignable<int, int&>(); 56 assert_assignable<int, int const&>(); 57 // Implicit test type 58 assert_assignable<I, I const&>(); 59 assert_assignable<I, I&&>(); 60 assert_assignable<I, int>(); 61 assert_assignable<I, void*, false>(); 62 // Explicit test type 63 assert_assignable<E, E const&>(); 64 assert_assignable<E, E &&>(); 65 assert_assignable<E, int>(); 66 assert_assignable<E, void*, false>(); 67 // Mismatch type 68 assert_assignable<MismatchType, int>(); 69 assert_assignable<MismatchType, int*, false>(); 70 assert_assignable<MismatchType, char*, false>(); 71 } 72 73 void test_with_test_type() 74 { 75 using T = TestTypes::TestType; 76 T::reset(); 77 { // to empty 78 optional<T> opt; 79 opt = 3; 80 assert(T::alive == 1); 81 assert(T::constructed == 1); 82 assert(T::value_constructed == 1); 83 assert(T::assigned == 0); 84 assert(T::destroyed == 0); 85 assert(static_cast<bool>(opt) == true); 86 assert(*opt == T(3)); 87 } 88 { // to existing 89 optional<T> opt(42); 90 T::reset_constructors(); 91 opt = 3; 92 assert(T::alive == 1); 93 assert(T::constructed == 0); 94 assert(T::assigned == 1); 95 assert(T::value_assigned == 1); 96 assert(T::destroyed == 0); 97 assert(static_cast<bool>(opt) == true); 98 assert(*opt == T(3)); 99 } 100 { // test default argument 101 optional<T> opt; 102 T::reset_constructors(); 103 opt = {1, 2}; 104 assert(T::alive == 1); 105 assert(T::constructed == 2); 106 assert(T::value_constructed == 1); 107 assert(T::move_constructed == 1); 108 assert(T::assigned == 0); 109 assert(T::destroyed == 1); 110 assert(static_cast<bool>(opt) == true); 111 assert(*opt == T(1, 2)); 112 } 113 { // test default argument 114 optional<T> opt(42); 115 T::reset_constructors(); 116 opt = {1, 2}; 117 assert(T::alive == 1); 118 assert(T::constructed == 1); 119 assert(T::value_constructed == 1); 120 assert(T::assigned == 1); 121 assert(T::move_assigned == 1); 122 assert(T::destroyed == 1); 123 assert(static_cast<bool>(opt) == true); 124 assert(*opt == T(1, 2)); 125 } 126 { // test default argument 127 optional<T> opt; 128 T::reset_constructors(); 129 opt = {1}; 130 assert(T::alive == 1); 131 assert(T::constructed == 2); 132 assert(T::value_constructed == 1); 133 assert(T::move_constructed == 1); 134 assert(T::assigned == 0); 135 assert(T::destroyed == 1); 136 assert(static_cast<bool>(opt) == true); 137 assert(*opt == T(1)); 138 } 139 { // test default argument 140 optional<T> opt(42); 141 T::reset_constructors(); 142 opt = {}; 143 assert(static_cast<bool>(opt) == false); 144 assert(T::alive == 0); 145 assert(T::constructed == 0); 146 assert(T::assigned == 0); 147 assert(T::destroyed == 1); 148 } 149 } 150 151 template <class T, class Value = int> 152 void test_with_type() { 153 { // to empty 154 optional<T> opt; 155 opt = Value(3); 156 assert(static_cast<bool>(opt) == true); 157 assert(*opt == T(3)); 158 } 159 { // to existing 160 optional<T> opt(Value(42)); 161 opt = Value(3); 162 assert(static_cast<bool>(opt) == true); 163 assert(*opt == T(3)); 164 } 165 { // test const 166 optional<T> opt(Value(42)); 167 const T t(Value(3)); 168 opt = t; 169 assert(static_cast<bool>(opt) == true); 170 assert(*opt == T(3)); 171 } 172 { // test default argument 173 optional<T> opt; 174 opt = {Value(1)}; 175 assert(static_cast<bool>(opt) == true); 176 assert(*opt == T(1)); 177 } 178 { // test default argument 179 optional<T> opt(Value(42)); 180 opt = {}; 181 assert(static_cast<bool>(opt) == false); 182 } 183 } 184 185 template <class T> 186 void test_with_type_multi() { 187 test_with_type<T>(); 188 { // test default argument 189 optional<T> opt; 190 opt = {1, 2}; 191 assert(static_cast<bool>(opt) == true); 192 assert(*opt == T(1, 2)); 193 } 194 { // test default argument 195 optional<T> opt(42); 196 opt = {1, 2}; 197 assert(static_cast<bool>(opt) == true); 198 assert(*opt == T(1, 2)); 199 } 200 } 201 202 void test_throws() 203 { 204 #ifndef TEST_HAS_NO_EXCEPTIONS 205 using T = ThrowAssign; 206 { 207 using T = ThrowAssign; 208 optional<T> opt; 209 try { 210 opt = 42; 211 assert(false); 212 } catch (int) {} 213 assert(static_cast<bool>(opt) == false); 214 } 215 assert(T::dtor_called == 0); 216 { 217 T::dtor_called = 0; 218 optional<T> opt(std::in_place); 219 try { 220 opt = 42; 221 assert(false); 222 } catch (int) {} 223 assert(static_cast<bool>(opt) == true); 224 assert(T::dtor_called == 0); 225 } 226 assert(T::dtor_called == 1); 227 #endif 228 } 229 230 enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 }; 231 232 using Fn = void(*)(); 233 234 int main() 235 { 236 test_sfinae(); 237 // Test with instrumented type 238 test_with_test_type(); 239 // Test with various scalar types 240 test_with_type<int>(); 241 test_with_type<MyEnum, MyEnum>(); 242 test_with_type<int, MyEnum>(); 243 test_with_type<Fn, Fn>(); 244 // Test types with multi argument constructors 245 test_with_type_multi<ConstexprTestTypes::TestType>(); 246 test_with_type_multi<TrivialTestTypes::TestType>(); 247 // Test move only types 248 { 249 optional<std::unique_ptr<int>> opt; 250 opt = std::unique_ptr<int>(new int(3)); 251 assert(static_cast<bool>(opt) == true); 252 assert(**opt == 3); 253 } 254 { 255 optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2))); 256 opt = std::unique_ptr<int>(new int(3)); 257 assert(static_cast<bool>(opt) == true); 258 assert(**opt == 3); 259 } 260 test_throws(); 261 } 262