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 U, class... Args>
13 //   T& optional<T>::emplace(initializer_list<U> il, Args&&... args);
14 
15 #include <optional>
16 #include <type_traits>
17 #include <cassert>
18 #include <vector>
19 
20 #include "test_macros.h"
21 
22 using std::optional;
23 
24 class X
25 {
26     int i_;
27     int j_ = 0;
28     bool* dtor_called_;
29 public:
X(bool & dtor_called)30     constexpr X(bool& dtor_called) : i_(0), dtor_called_(&dtor_called) {}
X(int i,bool & dtor_called)31     constexpr X(int i, bool& dtor_called) : i_(i), dtor_called_(&dtor_called) {}
X(std::initializer_list<int> il,bool & dtor_called)32     constexpr X(std::initializer_list<int> il, bool& dtor_called)
33     : i_(il.begin()[0]), j_(il.begin()[1]), dtor_called_(&dtor_called) {}
~X()34     TEST_CONSTEXPR_CXX20 ~X() {*dtor_called_ = true;}
35 
operator ==(const X & x,const X & y)36     friend constexpr bool operator==(const X& x, const X& y)
37         {return x.i_ == y.i_ && x.j_ == y.j_;}
38 };
39 
40 class Y
41 {
42     int i_;
43     int j_ = 0;
44 public:
Y()45     constexpr Y() : i_(0) {}
Y(int i)46     constexpr Y(int i) : i_(i) {}
Y(std::initializer_list<int> il)47     constexpr Y(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {}
48 
operator ==(const Y & x,const Y & y)49     friend constexpr bool operator==(const Y& x, const Y& y)
50         {return x.i_ == y.i_ && x.j_ == y.j_;}
51 };
52 
53 class Z
54 {
55     int i_;
56     int j_ = 0;
57 public:
58     static bool dtor_called;
Z()59     Z() : i_(0) {}
Z(int i)60     Z(int i) : i_(i) {}
Z(std::initializer_list<int> il)61     Z(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1])
62         { TEST_THROW(6);}
~Z()63     ~Z() {dtor_called = true;}
64 
operator ==(const Z & x,const Z & y)65     friend bool operator==(const Z& x, const Z& y)
66         {return x.i_ == y.i_ && x.j_ == y.j_;}
67 };
68 
69 bool Z::dtor_called = false;
70 
check_X()71 TEST_CONSTEXPR_CXX20 bool check_X()
72 {
73     bool dtor_called = false;
74     X x(dtor_called);
75     optional<X> opt(x);
76     assert(dtor_called == false);
77     auto &v = opt.emplace({1, 2}, dtor_called);
78     static_assert( std::is_same_v<X&, decltype(v)>, "" );
79     assert(dtor_called);
80     assert(*opt == X({1, 2}, dtor_called));
81     assert(&v == &*opt);
82     return true;
83 }
84 
check_Y()85 TEST_CONSTEXPR_CXX20 bool check_Y()
86 {
87     optional<Y> opt;
88     auto &v = opt.emplace({1, 2});
89     static_assert( std::is_same_v<Y&, decltype(v)>, "" );
90     assert(static_cast<bool>(opt) == true);
91     assert(*opt == Y({1, 2}));
92     assert(&v == &*opt);
93     return true;
94 }
95 
main(int,char **)96 int main(int, char**)
97 {
98     {
99         check_X();
100 #if TEST_STD_VER > 17
101         static_assert(check_X());
102 #endif
103     }
104     {
105         optional<std::vector<int>> opt;
106         auto &v = opt.emplace({1, 2, 3}, std::allocator<int>());
107         static_assert( std::is_same_v<std::vector<int>&, decltype(v)>, "" );
108         assert(static_cast<bool>(opt) == true);
109         assert(*opt == std::vector<int>({1, 2, 3}));
110         assert(&v == &*opt);
111     }
112     {
113         check_Y();
114 #if TEST_STD_VER > 17
115         static_assert(check_Y());
116 #endif
117     }
118 #ifndef TEST_HAS_NO_EXCEPTIONS
119     {
120         Z z;
121         optional<Z> opt(z);
122         try
123         {
124             assert(static_cast<bool>(opt) == true);
125             assert(Z::dtor_called == false);
126             auto &v = opt.emplace({1, 2});
127             static_assert( std::is_same_v<Z&, decltype(v)>, "" );
128             assert(false);
129         }
130         catch (int i)
131         {
132             assert(i == 6);
133             assert(static_cast<bool>(opt) == false);
134             assert(Z::dtor_called == true);
135         }
136     }
137 #endif
138 
139   return 0;
140 }
141