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