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 // template <class... Args> T& optional<T>::emplace(Args&&... args); 13 14 #include <optional> 15 #include <type_traits> 16 #include <cassert> 17 #include <memory> 18 19 #include "test_macros.h" 20 #include "archetypes.h" 21 22 using std::optional; 23 24 class X 25 { 26 int i_; 27 int j_ = 0; 28 public: 29 constexpr X() : i_(0) {} 30 constexpr X(int i) : i_(i) {} 31 constexpr X(int i, int j) : i_(i), j_(j) {} 32 33 friend constexpr bool operator==(const X& x, const X& y) 34 {return x.i_ == y.i_ && x.j_ == y.j_;} 35 }; 36 37 class Y 38 { 39 public: 40 static bool dtor_called; 41 Y() = default; 42 Y(int) { TEST_THROW(6);} 43 ~Y() {dtor_called = true;} 44 }; 45 46 bool Y::dtor_called = false; 47 48 template <class T> 49 constexpr bool test_one_arg() { 50 using Opt = std::optional<T>; 51 { 52 Opt opt; 53 auto & v = opt.emplace(); 54 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 55 assert(static_cast<bool>(opt) == true); 56 assert(*opt == T(0)); 57 assert(&v == &*opt); 58 } 59 { 60 Opt opt; 61 auto & v = opt.emplace(1); 62 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 63 assert(static_cast<bool>(opt) == true); 64 assert(*opt == T(1)); 65 assert(&v == &*opt); 66 } 67 { 68 Opt opt(2); 69 auto & v = opt.emplace(); 70 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 71 assert(static_cast<bool>(opt) == true); 72 assert(*opt == T(0)); 73 assert(&v == &*opt); 74 } 75 { 76 Opt opt(2); 77 auto & v = opt.emplace(1); 78 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 79 assert(static_cast<bool>(opt) == true); 80 assert(*opt == T(1)); 81 assert(&v == &*opt); 82 } 83 return true; 84 } 85 86 87 template <class T> 88 constexpr bool test_multi_arg() 89 { 90 test_one_arg<T>(); 91 using Opt = std::optional<T>; 92 { 93 Opt opt; 94 auto &v = opt.emplace(101, 41); 95 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 96 assert(static_cast<bool>(opt) == true); 97 assert( v == T(101, 41)); 98 assert(*opt == T(101, 41)); 99 } 100 { 101 Opt opt; 102 auto &v = opt.emplace({1, 2, 3, 4}); 103 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 104 assert(static_cast<bool>(opt) == true); 105 assert( v == T(4)); // T sets its value to the size of the init list 106 assert(*opt == T(4)); 107 } 108 { 109 Opt opt; 110 auto &v = opt.emplace({1, 2, 3, 4, 5}, 6); 111 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 112 assert(static_cast<bool>(opt) == true); 113 assert( v == T(5)); // T sets its value to the size of the init list 114 assert(*opt == T(5)); // T sets its value to the size of the init list 115 } 116 return true; 117 } 118 119 template <class T> 120 void test_on_test_type() { 121 122 T::reset(); 123 optional<T> opt; 124 assert(T::alive == 0); 125 { 126 T::reset_constructors(); 127 auto &v = opt.emplace(); 128 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 129 assert(T::alive == 1); 130 assert(T::constructed == 1); 131 assert(T::default_constructed == 1); 132 assert(T::destroyed == 0); 133 assert(static_cast<bool>(opt) == true); 134 assert(*opt == T()); 135 assert(&v == &*opt); 136 } 137 { 138 T::reset_constructors(); 139 auto &v = opt.emplace(); 140 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 141 assert(T::alive == 1); 142 assert(T::constructed == 1); 143 assert(T::default_constructed == 1); 144 assert(T::destroyed == 1); 145 assert(static_cast<bool>(opt) == true); 146 assert(*opt == T()); 147 assert(&v == &*opt); 148 } 149 { 150 T::reset_constructors(); 151 auto &v = opt.emplace(101); 152 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 153 assert(T::alive == 1); 154 assert(T::constructed == 1); 155 assert(T::value_constructed == 1); 156 assert(T::destroyed == 1); 157 assert(static_cast<bool>(opt) == true); 158 assert(*opt == T(101)); 159 assert(&v == &*opt); 160 } 161 { 162 T::reset_constructors(); 163 auto &v = opt.emplace(-10, 99); 164 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 165 assert(T::alive == 1); 166 assert(T::constructed == 1); 167 assert(T::value_constructed == 1); 168 assert(T::destroyed == 1); 169 assert(static_cast<bool>(opt) == true); 170 assert(*opt == T(-10, 99)); 171 assert(&v == &*opt); 172 } 173 { 174 T::reset_constructors(); 175 auto &v = opt.emplace(-10, 99); 176 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 177 assert(T::alive == 1); 178 assert(T::constructed == 1); 179 assert(T::value_constructed == 1); 180 assert(T::destroyed == 1); 181 assert(static_cast<bool>(opt) == true); 182 assert(*opt == T(-10, 99)); 183 assert(&v == &*opt); 184 } 185 { 186 T::reset_constructors(); 187 auto &v = opt.emplace({-10, 99, 42, 1}); 188 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 189 assert(T::alive == 1); 190 assert(T::constructed == 1); 191 assert(T::value_constructed == 1); 192 assert(T::destroyed == 1); 193 assert(static_cast<bool>(opt) == true); 194 assert(*opt == T(4)); // size of the initializer list 195 assert(&v == &*opt); 196 } 197 { 198 T::reset_constructors(); 199 auto &v = opt.emplace({-10, 99, 42, 1}, 42); 200 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 201 assert(T::alive == 1); 202 assert(T::constructed == 1); 203 assert(T::value_constructed == 1); 204 assert(T::destroyed == 1); 205 assert(static_cast<bool>(opt) == true); 206 assert(*opt == T(4)); // size of the initializer list 207 assert(&v == &*opt); 208 } 209 } 210 211 constexpr bool test_empty_emplace() 212 { 213 optional<const int> opt; 214 auto &v = opt.emplace(42); 215 static_assert( std::is_same_v<const int&, decltype(v)>, "" ); 216 assert(*opt == 42); 217 assert( v == 42); 218 opt.emplace(); 219 assert(*opt == 0); 220 return true; 221 } 222 223 int main(int, char**) 224 { 225 { 226 test_on_test_type<TestTypes::TestType>(); 227 test_on_test_type<ExplicitTestTypes::TestType>(); 228 } 229 { 230 using T = int; 231 test_one_arg<T>(); 232 test_one_arg<const T>(); 233 #if TEST_STD_VER > 17 234 static_assert(test_one_arg<T>()); 235 static_assert(test_one_arg<const T>()); 236 #endif 237 } 238 { 239 using T = ConstexprTestTypes::TestType; 240 test_multi_arg<T>(); 241 #if TEST_STD_VER > 17 242 static_assert(test_multi_arg<T>()); 243 #endif 244 } 245 { 246 using T = ExplicitConstexprTestTypes::TestType; 247 test_multi_arg<T>(); 248 #if TEST_STD_VER > 17 249 static_assert(test_multi_arg<T>()); 250 #endif 251 } 252 { 253 using T = TrivialTestTypes::TestType; 254 test_multi_arg<T>(); 255 #if TEST_STD_VER > 17 256 static_assert(test_multi_arg<T>()); 257 #endif 258 } 259 { 260 using T = ExplicitTrivialTestTypes::TestType; 261 test_multi_arg<T>(); 262 #if TEST_STD_VER > 17 263 static_assert(test_multi_arg<T>()); 264 #endif 265 } 266 { 267 test_empty_emplace(); 268 #if TEST_STD_VER > 17 269 static_assert(test_empty_emplace()); 270 #endif 271 } 272 #ifndef TEST_HAS_NO_EXCEPTIONS 273 Y::dtor_called = false; 274 { 275 Y y; 276 optional<Y> opt(y); 277 try 278 { 279 assert(static_cast<bool>(opt) == true); 280 assert(Y::dtor_called == false); 281 auto &v = opt.emplace(1); 282 static_assert( std::is_same_v<Y&, decltype(v)>, "" ); 283 assert(false); 284 } 285 catch (int i) 286 { 287 assert(i == 6); 288 assert(static_cast<bool>(opt) == false); 289 assert(Y::dtor_called == true); 290 } 291 } 292 #endif 293 294 return 0; 295 } 296