320 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410// <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 22using std::optional;23 24class X25{26 int i_;27 int j_ = 0;28public: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 37class Y38{39public:40 static bool dtor_called;41 Y() = default;42 Y(int) { TEST_THROW(6);}43 Y(const Y&) = default;44 Y& operator=(const Y&) = default;45 ~Y() {dtor_called = true;}46};47 48bool Y::dtor_called = false;49 50template <class T>51constexpr bool test_one_arg() {52 using Opt = std::optional<T>;53 {54 Opt opt;55 auto & v = opt.emplace();56 static_assert( std::is_same_v<T&, decltype(v)>, "" );57 assert(static_cast<bool>(opt) == true);58 assert(*opt == T(0));59 assert(&v == &*opt);60 }61 {62 Opt opt;63 auto & v = opt.emplace(1);64 static_assert( std::is_same_v<T&, decltype(v)>, "" );65 assert(static_cast<bool>(opt) == true);66 assert(*opt == T(1));67 assert(&v == &*opt);68 }69 {70 Opt opt(2);71 auto & v = opt.emplace();72 static_assert( std::is_same_v<T&, decltype(v)>, "" );73 assert(static_cast<bool>(opt) == true);74 assert(*opt == T(0));75 assert(&v == &*opt);76 }77 {78 Opt opt(2);79 auto & v = opt.emplace(1);80 static_assert( std::is_same_v<T&, decltype(v)>, "" );81 assert(static_cast<bool>(opt) == true);82 assert(*opt == T(1));83 assert(&v == &*opt);84 }85 return true;86}87 88 89template <class T>90constexpr bool test_multi_arg()91{92 test_one_arg<T>();93 using Opt = std::optional<T>;94 {95 Opt opt;96 auto &v = opt.emplace(101, 41);97 static_assert( std::is_same_v<T&, decltype(v)>, "" );98 assert(static_cast<bool>(opt) == true);99 assert( v == T(101, 41));100 assert(*opt == T(101, 41));101 }102 {103 Opt opt;104 auto &v = opt.emplace({1, 2, 3, 4});105 static_assert( std::is_same_v<T&, decltype(v)>, "" );106 assert(static_cast<bool>(opt) == true);107 assert( v == T(4)); // T sets its value to the size of the init list108 assert(*opt == T(4));109 }110 {111 Opt opt;112 auto &v = opt.emplace({1, 2, 3, 4, 5}, 6);113 static_assert( std::is_same_v<T&, decltype(v)>, "" );114 assert(static_cast<bool>(opt) == true);115 assert( v == T(5)); // T sets its value to the size of the init list116 assert(*opt == T(5)); // T sets its value to the size of the init list117 }118 return true;119}120 121template <class T>122void test_on_test_type() {123 124 T::reset();125 optional<T> opt;126 assert(T::alive == 0);127 {128 T::reset_constructors();129 auto &v = opt.emplace();130 static_assert( std::is_same_v<T&, decltype(v)>, "" );131 assert(T::alive == 1);132 assert(T::constructed == 1);133 assert(T::default_constructed == 1);134 assert(T::destroyed == 0);135 assert(static_cast<bool>(opt) == true);136 assert(*opt == T());137 assert(&v == &*opt);138 }139 {140 T::reset_constructors();141 auto &v = opt.emplace();142 static_assert( std::is_same_v<T&, decltype(v)>, "" );143 assert(T::alive == 1);144 assert(T::constructed == 1);145 assert(T::default_constructed == 1);146 assert(T::destroyed == 1);147 assert(static_cast<bool>(opt) == true);148 assert(*opt == T());149 assert(&v == &*opt);150 }151 {152 T::reset_constructors();153 auto &v = opt.emplace(101);154 static_assert( std::is_same_v<T&, decltype(v)>, "" );155 assert(T::alive == 1);156 assert(T::constructed == 1);157 assert(T::value_constructed == 1);158 assert(T::destroyed == 1);159 assert(static_cast<bool>(opt) == true);160 assert(*opt == T(101));161 assert(&v == &*opt);162 }163 {164 T::reset_constructors();165 auto &v = opt.emplace(-10, 99);166 static_assert( std::is_same_v<T&, decltype(v)>, "" );167 assert(T::alive == 1);168 assert(T::constructed == 1);169 assert(T::value_constructed == 1);170 assert(T::destroyed == 1);171 assert(static_cast<bool>(opt) == true);172 assert(*opt == T(-10, 99));173 assert(&v == &*opt);174 }175 {176 T::reset_constructors();177 auto &v = opt.emplace(-10, 99);178 static_assert( std::is_same_v<T&, decltype(v)>, "" );179 assert(T::alive == 1);180 assert(T::constructed == 1);181 assert(T::value_constructed == 1);182 assert(T::destroyed == 1);183 assert(static_cast<bool>(opt) == true);184 assert(*opt == T(-10, 99));185 assert(&v == &*opt);186 }187 {188 T::reset_constructors();189 auto &v = opt.emplace({-10, 99, 42, 1});190 static_assert( std::is_same_v<T&, decltype(v)>, "" );191 assert(T::alive == 1);192 assert(T::constructed == 1);193 assert(T::value_constructed == 1);194 assert(T::destroyed == 1);195 assert(static_cast<bool>(opt) == true);196 assert(*opt == T(4)); // size of the initializer list197 assert(&v == &*opt);198 }199 {200 T::reset_constructors();201 auto &v = opt.emplace({-10, 99, 42, 1}, 42);202 static_assert( std::is_same_v<T&, decltype(v)>, "" );203 assert(T::alive == 1);204 assert(T::constructed == 1);205 assert(T::value_constructed == 1);206 assert(T::destroyed == 1);207 assert(static_cast<bool>(opt) == true);208 assert(*opt == T(4)); // size of the initializer list209 assert(&v == &*opt);210 }211}212 213TEST_CONSTEXPR_CXX20 bool test_empty_emplace() {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#if TEST_STD_VER >= 26225template <class T, std::remove_reference_t<T> _Val>226constexpr bool test_ref() {227 using Opt = std::optional<T&>;228 T t{_Val};229 {230 Opt opt;231 auto& v = opt.emplace(t);232 static_assert(std::is_same_v<T&, decltype(v)>);233 assert(static_cast<bool>(opt) == true);234 assert(*opt == t);235 assert(&v == &*opt);236 assert(&t == &*opt);237 }238 return true;239}240#endif241 242int main(int, char**)243{244 {245 test_on_test_type<TestTypes::TestType>();246 test_on_test_type<ExplicitTestTypes::TestType>();247 }248 {249 using T = int;250 test_one_arg<T>();251 test_one_arg<const T>();252#if TEST_STD_VER > 17253 static_assert(test_one_arg<T>());254 static_assert(test_one_arg<const T>());255#endif256 }257 {258 using T = ConstexprTestTypes::TestType;259 test_multi_arg<T>();260#if TEST_STD_VER > 17261 static_assert(test_multi_arg<T>());262#endif263 }264 {265 using T = ExplicitConstexprTestTypes::TestType;266 test_multi_arg<T>();267#if TEST_STD_VER > 17268 static_assert(test_multi_arg<T>());269#endif270 }271 {272 using T = TrivialTestTypes::TestType;273 test_multi_arg<T>();274#if TEST_STD_VER > 17275 static_assert(test_multi_arg<T>());276#endif277 }278 {279 using T = ExplicitTrivialTestTypes::TestType;280 test_multi_arg<T>();281#if TEST_STD_VER > 17282 static_assert(test_multi_arg<T>());283#endif284 }285 {286 test_empty_emplace();287#if TEST_STD_VER > 17288 static_assert(test_empty_emplace());289#endif290 }291#ifndef TEST_HAS_NO_EXCEPTIONS292 Y::dtor_called = false;293 {294 Y y;295 optional<Y> opt(y);296 try297 {298 assert(static_cast<bool>(opt) == true);299 assert(Y::dtor_called == false);300 auto &v = opt.emplace(1);301 static_assert( std::is_same_v<Y&, decltype(v)>, "" );302 assert(false);303 }304 catch (int i)305 {306 assert(i == 6);307 assert(static_cast<bool>(opt) == false);308 assert(Y::dtor_called == true);309 }310 }311#endif312#if TEST_STD_VER >= 26313 static_assert(test_ref<int, 1>());314 static_assert(test_ref<double, 15.0>());315 assert((test_ref<int, 1>()));316 assert((test_ref<double, 15.0>()));317#endif318 return 0;319}320