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// UNSUPPORTED: c++98, c++03, c++11, c++14
11// <optional>
12
13// optional<T>& operator=(const optional<T>& rhs);
14
15#include <optional>
16#include <type_traits>
17#include <cassert>
18
19#include "test_macros.h"
20#include "archetypes.hpp"
21
22using std::optional;
23
24struct X
25{
26    static bool throw_now;
27
28    X() = default;
29    X(const X&)
30    {
31        if (throw_now)
32            TEST_THROW(6);
33    }
34};
35
36bool X::throw_now = false;
37
38template <class Tp>
39constexpr bool assign_empty(optional<Tp>&& lhs) {
40    const optional<Tp> rhs;
41    lhs = rhs;
42    return !lhs.has_value() && !rhs.has_value();
43}
44
45template <class Tp>
46constexpr bool assign_value(optional<Tp>&& lhs) {
47    const optional<Tp> rhs(101);
48    lhs = rhs;
49    return lhs.has_value() && rhs.has_value() && *lhs == *rhs;
50}
51
52int main()
53{
54    {
55        using O = optional<int>;
56        LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
57        LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
58        assert(assign_empty(O{42}));
59        assert(assign_value(O{42}));
60    }
61    {
62        using O = optional<TrivialTestTypes::TestType>;
63        LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
64        LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
65        assert(assign_empty(O{42}));
66        assert(assign_value(O{42}));
67    }
68    {
69        using O = optional<TestTypes::TestType>;
70        assert(assign_empty(O{42}));
71        assert(assign_value(O{42}));
72    }
73    {
74        using T = TestTypes::TestType;
75        T::reset();
76        optional<T> opt(3);
77        const optional<T> opt2;
78        assert(T::alive == 1);
79        opt = opt2;
80        assert(T::alive == 0);
81        assert(!opt2.has_value());
82        assert(!opt.has_value());
83    }
84#ifndef TEST_HAS_NO_EXCEPTIONS
85    {
86        optional<X> opt;
87        optional<X> opt2(X{});
88        assert(static_cast<bool>(opt2) == true);
89        try
90        {
91            X::throw_now = true;
92            opt = opt2;
93            assert(false);
94        }
95        catch (int i)
96        {
97            assert(i == 6);
98            assert(static_cast<bool>(opt) == false);
99        }
100    }
101#endif
102}
103