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