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