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// optional<T>& operator=(optional<T>&& rhs)
13//     noexcept(is_nothrow_move_assignable<T>::value &&
14//              is_nothrow_move_constructible<T>::value);
15
16#include <experimental/optional>
17#include <type_traits>
18#include <cassert>
19
20#if _LIBCPP_STD_VER > 11
21
22using std::experimental::optional;
23
24struct X
25{
26    static bool throw_now;
27
28    X() = default;
29    X(X&&)
30    {
31        if (throw_now)
32            throw 6;
33    }
34    X& operator=(X&&) noexcept
35    {
36        return *this;
37    }
38};
39
40struct Y {};
41
42bool X::throw_now = false;
43
44#endif  // _LIBCPP_STD_VER > 11
45
46int main()
47{
48#if _LIBCPP_STD_VER > 11
49    {
50        static_assert(std::is_nothrow_move_assignable<optional<int>>::value, "");
51        optional<int> opt;
52        constexpr optional<int> opt2;
53        opt = std::move(opt2);
54        static_assert(static_cast<bool>(opt2) == false, "");
55        assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
56    }
57    {
58        optional<int> opt;
59        constexpr optional<int> opt2(2);
60        opt = std::move(opt2);
61        static_assert(static_cast<bool>(opt2) == true, "");
62        static_assert(*opt2 == 2, "");
63        assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
64        assert(*opt == *opt2);
65    }
66    {
67        optional<int> opt(3);
68        constexpr optional<int> opt2;
69        opt = std::move(opt2);
70        static_assert(static_cast<bool>(opt2) == false, "");
71        assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
72    }
73    {
74        optional<int> opt(3);
75        constexpr optional<int> opt2(2);
76        opt = std::move(opt2);
77        static_assert(static_cast<bool>(opt2) == true, "");
78        static_assert(*opt2 == 2, "");
79        assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
80        assert(*opt == *opt2);
81    }
82    {
83        static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
84        optional<X> opt;
85        optional<X> opt2(X{});
86        assert(static_cast<bool>(opt2) == true);
87        try
88        {
89            X::throw_now = true;
90            opt = std::move(opt2);
91            assert(false);
92        }
93        catch (int i)
94        {
95            assert(i == 6);
96            assert(static_cast<bool>(opt) == false);
97        }
98    }
99    {
100        static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, "");
101    }
102#endif  // _LIBCPP_STD_VER > 11
103}
104