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