1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// XFAIL: libcpp-no-exceptions
11// <optional>
12
13// template <class... Args> void optional<T>::emplace(Args&&... args);
14
15#include <experimental/optional>
16#include <type_traits>
17#include <cassert>
18#include <memory>
19
20#if _LIBCPP_STD_VER > 11
21
22using std::experimental::optional;
23
24class X
25{
26    int i_;
27    int j_ = 0;
28public:
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
37class Y
38{
39public:
40    static bool dtor_called;
41    Y() = default;
42    ~Y() {dtor_called = true;}
43};
44
45bool Y::dtor_called = false;
46
47class Z
48{
49public:
50    static bool dtor_called;
51    Z() = default;
52    Z(int) {throw 6;}
53    ~Z() {dtor_called = true;}
54};
55
56bool Z::dtor_called = false;
57
58#endif  // _LIBCPP_STD_VER > 11
59
60int main()
61{
62#if _LIBCPP_STD_VER > 11
63    {
64        optional<int> opt;
65        opt.emplace();
66        assert(static_cast<bool>(opt) == true);
67        assert(*opt == 0);
68    }
69    {
70        optional<int> opt;
71        opt.emplace(1);
72        assert(static_cast<bool>(opt) == true);
73        assert(*opt == 1);
74    }
75    {
76        optional<int> opt(2);
77        opt.emplace();
78        assert(static_cast<bool>(opt) == true);
79        assert(*opt == 0);
80    }
81    {
82        optional<int> opt(2);
83        opt.emplace(1);
84        assert(static_cast<bool>(opt) == true);
85        assert(*opt == 1);
86    }
87    {
88        optional<X> opt;
89        opt.emplace();
90        assert(static_cast<bool>(opt) == true);
91        assert(*opt == X());
92    }
93    {
94        optional<X> opt;
95        opt.emplace(1);
96        assert(static_cast<bool>(opt) == true);
97        assert(*opt == X(1));
98    }
99    {
100        optional<X> opt;
101        opt.emplace(1, 2);
102        assert(static_cast<bool>(opt) == true);
103        assert(*opt == X(1, 2));
104    }
105    {
106        optional<X> opt(X{3});
107        opt.emplace();
108        assert(static_cast<bool>(opt) == true);
109        assert(*opt == X());
110    }
111    {
112        optional<X> opt(X{3});
113        opt.emplace(1);
114        assert(static_cast<bool>(opt) == true);
115        assert(*opt == X(1));
116    }
117    {
118        optional<X> opt(X{3});
119        opt.emplace(1, 2);
120        assert(static_cast<bool>(opt) == true);
121        assert(*opt == X(1, 2));
122    }
123    {
124        Y y;
125        {
126            optional<Y> opt(y);
127            assert(Y::dtor_called == false);
128            opt.emplace();
129            assert(Y::dtor_called == true);
130        }
131    }
132    {
133        Z z;
134        optional<Z> opt(z);
135        try
136        {
137            assert(static_cast<bool>(opt) == true);
138            assert(Z::dtor_called == false);
139            opt.emplace(1);
140        }
141        catch (int i)
142        {
143            assert(i == 6);
144            assert(static_cast<bool>(opt) == false);
145            assert(Z::dtor_called == true);
146        }
147    }
148#endif  // _LIBCPP_STD_VER > 11
149}
150