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 X() : i_(0) {} 30 X(int i) : i_(i) {} 31 X(int i, int j) : i_(i), j_(j) {} 32 33 friend 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 void 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 } 84 85 86 template <class T> 87 void test_multi_arg() 88 { 89 test_one_arg<T>(); 90 using Opt = std::optional<T>; 91 { 92 Opt opt; 93 auto &v = opt.emplace(101, 41); 94 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 95 assert(static_cast<bool>(opt) == true); 96 assert( v == T(101, 41)); 97 assert(*opt == T(101, 41)); 98 } 99 { 100 Opt opt; 101 auto &v = opt.emplace({1, 2, 3, 4}); 102 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 103 assert(static_cast<bool>(opt) == true); 104 assert( v == T(4)); // T sets its value to the size of the init list 105 assert(*opt == T(4)); 106 } 107 { 108 Opt opt; 109 auto &v = opt.emplace({1, 2, 3, 4, 5}, 6); 110 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 111 assert(static_cast<bool>(opt) == true); 112 assert( v == T(5)); // T sets its value to the size of the init list 113 assert(*opt == T(5)); // T sets its value to the size of the init list 114 } 115 } 116 117 template <class T> 118 void test_on_test_type() { 119 120 T::reset(); 121 optional<T> opt; 122 assert(T::alive == 0); 123 { 124 T::reset_constructors(); 125 auto &v = opt.emplace(); 126 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 127 assert(T::alive == 1); 128 assert(T::constructed == 1); 129 assert(T::default_constructed == 1); 130 assert(T::destroyed == 0); 131 assert(static_cast<bool>(opt) == true); 132 assert(*opt == T()); 133 assert(&v == &*opt); 134 } 135 { 136 T::reset_constructors(); 137 auto &v = opt.emplace(); 138 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 139 assert(T::alive == 1); 140 assert(T::constructed == 1); 141 assert(T::default_constructed == 1); 142 assert(T::destroyed == 1); 143 assert(static_cast<bool>(opt) == true); 144 assert(*opt == T()); 145 assert(&v == &*opt); 146 } 147 { 148 T::reset_constructors(); 149 auto &v = opt.emplace(101); 150 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 151 assert(T::alive == 1); 152 assert(T::constructed == 1); 153 assert(T::value_constructed == 1); 154 assert(T::destroyed == 1); 155 assert(static_cast<bool>(opt) == true); 156 assert(*opt == T(101)); 157 assert(&v == &*opt); 158 } 159 { 160 T::reset_constructors(); 161 auto &v = opt.emplace(-10, 99); 162 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 163 assert(T::alive == 1); 164 assert(T::constructed == 1); 165 assert(T::value_constructed == 1); 166 assert(T::destroyed == 1); 167 assert(static_cast<bool>(opt) == true); 168 assert(*opt == T(-10, 99)); 169 assert(&v == &*opt); 170 } 171 { 172 T::reset_constructors(); 173 auto &v = opt.emplace(-10, 99); 174 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 175 assert(T::alive == 1); 176 assert(T::constructed == 1); 177 assert(T::value_constructed == 1); 178 assert(T::destroyed == 1); 179 assert(static_cast<bool>(opt) == true); 180 assert(*opt == T(-10, 99)); 181 assert(&v == &*opt); 182 } 183 { 184 T::reset_constructors(); 185 auto &v = opt.emplace({-10, 99, 42, 1}); 186 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 187 assert(T::alive == 1); 188 assert(T::constructed == 1); 189 assert(T::value_constructed == 1); 190 assert(T::destroyed == 1); 191 assert(static_cast<bool>(opt) == true); 192 assert(*opt == T(4)); // size of the initializer list 193 assert(&v == &*opt); 194 } 195 { 196 T::reset_constructors(); 197 auto &v = opt.emplace({-10, 99, 42, 1}, 42); 198 static_assert( std::is_same_v<T&, decltype(v)>, "" ); 199 assert(T::alive == 1); 200 assert(T::constructed == 1); 201 assert(T::value_constructed == 1); 202 assert(T::destroyed == 1); 203 assert(static_cast<bool>(opt) == true); 204 assert(*opt == T(4)); // size of the initializer list 205 assert(&v == &*opt); 206 } 207 } 208 209 210 211 int main(int, char**) 212 { 213 { 214 test_on_test_type<TestTypes::TestType>(); 215 test_on_test_type<ExplicitTestTypes::TestType>(); 216 } 217 { 218 using T = int; 219 test_one_arg<T>(); 220 test_one_arg<const T>(); 221 } 222 { 223 using T = ConstexprTestTypes::TestType; 224 test_multi_arg<T>(); 225 } 226 { 227 using T = ExplicitConstexprTestTypes::TestType; 228 test_multi_arg<T>(); 229 } 230 { 231 using T = TrivialTestTypes::TestType; 232 test_multi_arg<T>(); 233 } 234 { 235 using T = ExplicitTrivialTestTypes::TestType; 236 test_multi_arg<T>(); 237 } 238 { 239 optional<const int> opt; 240 auto &v = opt.emplace(42); 241 static_assert( std::is_same_v<const int&, decltype(v)>, "" ); 242 assert(*opt == 42); 243 assert( v == 42); 244 opt.emplace(); 245 assert(*opt == 0); 246 } 247 #ifndef TEST_HAS_NO_EXCEPTIONS 248 Y::dtor_called = false; 249 { 250 Y y; 251 optional<Y> opt(y); 252 try 253 { 254 assert(static_cast<bool>(opt) == true); 255 assert(Y::dtor_called == false); 256 auto &v = opt.emplace(1); 257 static_assert( std::is_same_v<Y&, decltype(v)>, "" ); 258 assert(false); 259 } 260 catch (int i) 261 { 262 assert(i == 6); 263 assert(static_cast<bool>(opt) == false); 264 assert(Y::dtor_called == true); 265 } 266 } 267 #endif 268 269 return 0; 270 } 271