1a9e65961SEric Fiselier //===----------------------------------------------------------------------===//
2a9e65961SEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a9e65961SEric Fiselier //
7a9e65961SEric Fiselier //===----------------------------------------------------------------------===//
8a9e65961SEric Fiselier 
9*31cbe0f2SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
10a9e65961SEric Fiselier // <optional>
11a9e65961SEric Fiselier 
121d5f6a81SLouis Dionne // optional<T>& operator=(const optional<T>& rhs); // constexpr in C++20
13a9e65961SEric Fiselier 
14a9e65961SEric Fiselier #include <optional>
15a9e65961SEric Fiselier #include <type_traits>
16a9e65961SEric Fiselier #include <cassert>
17a9e65961SEric Fiselier 
18a9e65961SEric Fiselier #include "test_macros.h"
19cc89063bSNico Weber #include "archetypes.h"
20a9e65961SEric Fiselier 
21a9e65961SEric Fiselier using std::optional;
22a9e65961SEric Fiselier 
23a9e65961SEric Fiselier struct X
24a9e65961SEric Fiselier {
25a9e65961SEric Fiselier     static bool throw_now;
26a9e65961SEric Fiselier 
27a9e65961SEric Fiselier     X() = default;
XX28a9e65961SEric Fiselier     X(const X&)
29a9e65961SEric Fiselier     {
30a9e65961SEric Fiselier         if (throw_now)
31a9e65961SEric Fiselier             TEST_THROW(6);
32a9e65961SEric Fiselier     }
33f97936faSEric Fiselier     X& operator=(X const&) = default;
34a9e65961SEric Fiselier };
35a9e65961SEric Fiselier 
36a9e65961SEric Fiselier bool X::throw_now = false;
37a9e65961SEric Fiselier 
38a9e65961SEric Fiselier template <class Tp>
assign_empty(optional<Tp> && lhs)39a9e65961SEric Fiselier constexpr bool assign_empty(optional<Tp>&& lhs) {
40a9e65961SEric Fiselier     const optional<Tp> rhs;
41a9e65961SEric Fiselier     lhs = rhs;
42a9e65961SEric Fiselier     return !lhs.has_value() && !rhs.has_value();
43a9e65961SEric Fiselier }
44a9e65961SEric Fiselier 
45a9e65961SEric Fiselier template <class Tp>
assign_value(optional<Tp> && lhs)46a9e65961SEric Fiselier constexpr bool assign_value(optional<Tp>&& lhs) {
47a9e65961SEric Fiselier     const optional<Tp> rhs(101);
48a9e65961SEric Fiselier     lhs = rhs;
49a9e65961SEric Fiselier     return lhs.has_value() && rhs.has_value() && *lhs == *rhs;
50a9e65961SEric Fiselier }
51a9e65961SEric Fiselier 
main(int,char **)522df59c50SJF Bastien int main(int, char**)
53a9e65961SEric Fiselier {
54a9e65961SEric Fiselier     {
55a9e65961SEric Fiselier         using O = optional<int>;
561d5f6a81SLouis Dionne #if TEST_STD_VER > 17
57a9e65961SEric Fiselier         LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
58a9e65961SEric Fiselier         LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
591d5f6a81SLouis Dionne #endif
60a9e65961SEric Fiselier         assert(assign_empty(O{42}));
61a9e65961SEric Fiselier         assert(assign_value(O{42}));
62a9e65961SEric Fiselier     }
63a9e65961SEric Fiselier     {
64a9e65961SEric Fiselier         using O = optional<TrivialTestTypes::TestType>;
651d5f6a81SLouis Dionne #if TEST_STD_VER > 17
66a9e65961SEric Fiselier         LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
67a9e65961SEric Fiselier         LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
681d5f6a81SLouis Dionne #endif
69a9e65961SEric Fiselier         assert(assign_empty(O{42}));
70a9e65961SEric Fiselier         assert(assign_value(O{42}));
71a9e65961SEric Fiselier     }
72a9e65961SEric Fiselier     {
73a9e65961SEric Fiselier         using O = optional<TestTypes::TestType>;
74a9e65961SEric Fiselier         assert(assign_empty(O{42}));
75a9e65961SEric Fiselier         assert(assign_value(O{42}));
76a9e65961SEric Fiselier     }
77a9e65961SEric Fiselier     {
78a9e65961SEric Fiselier         using T = TestTypes::TestType;
79a9e65961SEric Fiselier         T::reset();
80a9e65961SEric Fiselier         optional<T> opt(3);
81a9e65961SEric Fiselier         const optional<T> opt2;
82a9e65961SEric Fiselier         assert(T::alive == 1);
83a9e65961SEric Fiselier         opt = opt2;
84a9e65961SEric Fiselier         assert(T::alive == 0);
85a9e65961SEric Fiselier         assert(!opt2.has_value());
86a9e65961SEric Fiselier         assert(!opt.has_value());
87a9e65961SEric Fiselier     }
88a9e65961SEric Fiselier #ifndef TEST_HAS_NO_EXCEPTIONS
89a9e65961SEric Fiselier     {
90a9e65961SEric Fiselier         optional<X> opt;
91a9e65961SEric Fiselier         optional<X> opt2(X{});
92a9e65961SEric Fiselier         assert(static_cast<bool>(opt2) == true);
93a9e65961SEric Fiselier         try
94a9e65961SEric Fiselier         {
95a9e65961SEric Fiselier             X::throw_now = true;
96a9e65961SEric Fiselier             opt = opt2;
97a9e65961SEric Fiselier             assert(false);
98a9e65961SEric Fiselier         }
99a9e65961SEric Fiselier         catch (int i)
100a9e65961SEric Fiselier         {
101a9e65961SEric Fiselier             assert(i == 6);
102a9e65961SEric Fiselier             assert(static_cast<bool>(opt) == false);
103a9e65961SEric Fiselier         }
104a9e65961SEric Fiselier     }
105a9e65961SEric Fiselier #endif
1062df59c50SJF Bastien 
1072df59c50SJF Bastien   return 0;
108a9e65961SEric Fiselier }
109