xref: /llvm-project/libcxx/test/std/utilities/expected/expected.void/assign/assign.copy.pass.cpp (revision 6a54dfbfe534276d644d7f9c027f0deeb748dd53)
1e356f681SHui Xie //===----------------------------------------------------------------------===//
2*6a54dfbfSLouis Dionne //
3e356f681SHui Xie // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e356f681SHui Xie // See https://llvm.org/LICENSE.txt for license information.
5e356f681SHui Xie // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e356f681SHui Xie //
7e356f681SHui Xie //===----------------------------------------------------------------------===//
8e356f681SHui Xie 
9e356f681SHui Xie // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10e356f681SHui Xie 
11e356f681SHui Xie // constexpr expected& operator=(const expected& rhs);
12e356f681SHui Xie //
13e356f681SHui Xie // Effects:
14e356f681SHui Xie // - If this->has_value() && rhs.has_value() is true, no effects.
15e356f681SHui Xie // - Otherwise, if this->has_value() is true, equivalent to: construct_at(addressof(unex), rhs.unex); has_val = false;
16e356f681SHui Xie // - Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true.
17e356f681SHui Xie // - Otherwise, equivalent to unex = rhs.error().
18e356f681SHui Xie //
19e356f681SHui Xie // Returns: *this.
20e356f681SHui Xie //
21e356f681SHui Xie // Remarks: This operator is defined as deleted unless is_copy_assignable_v<E> is true and is_copy_constructible_v<E> is true.
22e356f681SHui Xie 
23e356f681SHui Xie #include <cassert>
24e356f681SHui Xie #include <concepts>
25e356f681SHui Xie #include <expected>
26e356f681SHui Xie #include <type_traits>
27e356f681SHui Xie #include <utility>
28e356f681SHui Xie 
29e356f681SHui Xie #include "../../types.h"
30e356f681SHui Xie #include "test_macros.h"
31e356f681SHui Xie 
32e356f681SHui Xie struct NotCopyConstructible {
33e356f681SHui Xie   NotCopyConstructible(const NotCopyConstructible&)            = delete;
34e356f681SHui Xie   NotCopyConstructible& operator=(const NotCopyConstructible&) = default;
35e356f681SHui Xie };
36e356f681SHui Xie 
37e356f681SHui Xie struct NotCopyAssignable {
38e356f681SHui Xie   NotCopyAssignable(const NotCopyAssignable&)            = default;
39e356f681SHui Xie   NotCopyAssignable& operator=(const NotCopyAssignable&) = delete;
40e356f681SHui Xie };
41e356f681SHui Xie 
42e356f681SHui Xie // Test constraints
43e356f681SHui Xie static_assert(std::is_copy_assignable_v<std::expected<void, int>>);
44e356f681SHui Xie 
45e356f681SHui Xie // !is_copy_assignable_v<E>
46e356f681SHui Xie static_assert(!std::is_copy_assignable_v<std::expected<void, NotCopyAssignable>>);
47e356f681SHui Xie 
48e356f681SHui Xie // !is_copy_constructible_v<E>
49e356f681SHui Xie static_assert(!std::is_copy_assignable_v<std::expected<void, NotCopyConstructible>>);
50e356f681SHui Xie 
51e356f681SHui Xie constexpr bool test() {
52e356f681SHui Xie   // If this->has_value() && rhs.has_value() is true, no effects.
53e356f681SHui Xie   {
54e356f681SHui Xie     std::expected<void, int> e1;
55e356f681SHui Xie     std::expected<void, int> e2;
56e356f681SHui Xie     decltype(auto) x = (e1 = e2);
57e356f681SHui Xie     static_assert(std::same_as<decltype(x), std::expected<void, int>&>);
58e356f681SHui Xie     assert(&x == &e1);
59e356f681SHui Xie     assert(e1.has_value());
60e356f681SHui Xie   }
61e356f681SHui Xie 
62e356f681SHui Xie   // Otherwise, if this->has_value() is true, equivalent to: construct_at(addressof(unex), rhs.unex); has_val = false;
63e356f681SHui Xie   {
64e356f681SHui Xie     Traced::state state{};
65e356f681SHui Xie     std::expected<void, Traced> e1;
66e356f681SHui Xie     std::expected<void, Traced> e2(std::unexpect, state, 5);
67e356f681SHui Xie     decltype(auto) x = (e1 = e2);
68e356f681SHui Xie     static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
69e356f681SHui Xie     assert(&x == &e1);
70e356f681SHui Xie     assert(!e1.has_value());
71e356f681SHui Xie     assert(e1.error().data_ == 5);
72e356f681SHui Xie 
73e356f681SHui Xie     assert(state.copyCtorCalled);
74e356f681SHui Xie   }
75e356f681SHui Xie 
76e356f681SHui Xie   // Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true.
77e356f681SHui Xie   {
78e356f681SHui Xie     Traced::state state{};
79e356f681SHui Xie     std::expected<void, Traced> e1(std::unexpect, state, 5);
80e356f681SHui Xie     std::expected<void, Traced> e2;
81e356f681SHui Xie     decltype(auto) x = (e1 = e2);
82e356f681SHui Xie     static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
83e356f681SHui Xie     assert(&x == &e1);
84e356f681SHui Xie     assert(e1.has_value());
85e356f681SHui Xie 
86e356f681SHui Xie     assert(state.dtorCalled);
87e356f681SHui Xie   }
88e356f681SHui Xie 
89e356f681SHui Xie   // Otherwise, equivalent to unex = rhs.error().
90e356f681SHui Xie   {
91e356f681SHui Xie     Traced::state state{};
92e356f681SHui Xie     std::expected<void, Traced> e1(std::unexpect, state, 5);
93e356f681SHui Xie     std::expected<void, Traced> e2(std::unexpect, state, 10);
94e356f681SHui Xie     decltype(auto) x = (e1 = e2);
95e356f681SHui Xie     static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
96e356f681SHui Xie     assert(&x == &e1);
97e356f681SHui Xie     assert(!e1.has_value());
98e356f681SHui Xie     assert(e1.error().data_ == 10);
99e356f681SHui Xie 
100e356f681SHui Xie     assert(state.copyAssignCalled);
101e356f681SHui Xie   }
102e356f681SHui Xie 
1034f469053SJan Kokemüller   // CheckForInvalidWrites
1044f469053SJan Kokemüller   {
1054f469053SJan Kokemüller     {
1064f469053SJan Kokemüller       CheckForInvalidWrites<true, true> e1;
1074f469053SJan Kokemüller       CheckForInvalidWrites<true, true> e2(std::unexpect);
1084f469053SJan Kokemüller 
1094f469053SJan Kokemüller       e1 = e2;
1104f469053SJan Kokemüller 
1114f469053SJan Kokemüller       assert(e1.check());
1124f469053SJan Kokemüller       assert(e2.check());
1134f469053SJan Kokemüller     }
1144f469053SJan Kokemüller     {
1154f469053SJan Kokemüller       CheckForInvalidWrites<false, true> e1;
1164f469053SJan Kokemüller       CheckForInvalidWrites<false, true> e2(std::unexpect);
1174f469053SJan Kokemüller 
1184f469053SJan Kokemüller       e1 = e2;
1194f469053SJan Kokemüller 
1204f469053SJan Kokemüller       assert(e1.check());
1214f469053SJan Kokemüller       assert(e2.check());
1224f469053SJan Kokemüller     }
1234f469053SJan Kokemüller   }
1244f469053SJan Kokemüller 
125e356f681SHui Xie   return true;
126e356f681SHui Xie }
127e356f681SHui Xie 
128e356f681SHui Xie void testException() {
129e356f681SHui Xie #ifndef TEST_HAS_NO_EXCEPTIONS
130e356f681SHui Xie   std::expected<void, ThrowOnCopyConstruct> e1(std::in_place);
131e356f681SHui Xie   std::expected<void, ThrowOnCopyConstruct> e2(std::unexpect);
132e356f681SHui Xie   try {
133e356f681SHui Xie     e1 = e2;
134e356f681SHui Xie     assert(false);
135e356f681SHui Xie   } catch (Except) {
136e356f681SHui Xie     assert(e1.has_value());
137e356f681SHui Xie   }
138e356f681SHui Xie #endif // TEST_HAS_NO_EXCEPTIONS
139e356f681SHui Xie }
140e356f681SHui Xie 
141e356f681SHui Xie int main(int, char**) {
142e356f681SHui Xie   test();
143e356f681SHui Xie   static_assert(test());
144e356f681SHui Xie   testException();
145e356f681SHui Xie   return 0;
146e356f681SHui Xie }
147