xref: /llvm-project/libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.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 // template<class G>
12e356f681SHui Xie //   constexpr expected& operator=(const unexpected<G>& e);
13e356f681SHui Xie //
14e356f681SHui Xie // Let GF be const G&
15e356f681SHui Xie //
16e356f681SHui Xie // Constraints: is_constructible_v<E, GF> is true and is_assignable_v<E&, GF> is true.
17e356f681SHui Xie //
18e356f681SHui Xie // Effects:
19e356f681SHui Xie // - If has_value() is true, equivalent to:
20e356f681SHui Xie //   construct_at(addressof(unex), std::forward<GF>(e.error()));
21e356f681SHui Xie //   has_val = false;
22e356f681SHui Xie // - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
23e356f681SHui Xie //
24e356f681SHui Xie // Returns: *this.
25e356f681SHui Xie 
26e356f681SHui Xie #include <cassert>
27e356f681SHui Xie #include <concepts>
28e356f681SHui Xie #include <expected>
29e356f681SHui Xie #include <type_traits>
30e356f681SHui Xie #include <utility>
31e356f681SHui Xie 
32e356f681SHui Xie #include "../../types.h"
33e356f681SHui Xie #include "test_macros.h"
34e356f681SHui Xie 
35e356f681SHui Xie struct NotCopyConstructible {
36e356f681SHui Xie   NotCopyConstructible(const NotCopyConstructible&)            = delete;
37e356f681SHui Xie   NotCopyConstructible& operator=(const NotCopyConstructible&) = default;
38e356f681SHui Xie };
39e356f681SHui Xie 
40e356f681SHui Xie struct NotCopyAssignable {
41e356f681SHui Xie   NotCopyAssignable(const NotCopyAssignable&)            = default;
42e356f681SHui Xie   NotCopyAssignable& operator=(const NotCopyAssignable&) = delete;
43e356f681SHui Xie };
44e356f681SHui Xie 
45e356f681SHui Xie struct MoveMayThrow {
46e356f681SHui Xie   MoveMayThrow(MoveMayThrow const&)            = default;
47e356f681SHui Xie   MoveMayThrow& operator=(const MoveMayThrow&) = default;
48e356f681SHui Xie   MoveMayThrow(MoveMayThrow&&) noexcept(false) {}
49e356f681SHui Xie   MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) { return *this; }
50e356f681SHui Xie };
51e356f681SHui Xie 
52e356f681SHui Xie // Test constraints
53e356f681SHui Xie static_assert(std::is_assignable_v<std::expected<void, int>&, const std::unexpected<int>&>);
54e356f681SHui Xie 
55e356f681SHui Xie // !is_constructible_v<E, GF>
56e356f681SHui Xie static_assert(
57e356f681SHui Xie     !std::is_assignable_v<std::expected<void, NotCopyConstructible>&, const std::unexpected<NotCopyConstructible>&>);
58e356f681SHui Xie 
59e356f681SHui Xie // !is_assignable_v<E&, GF>
60e356f681SHui Xie static_assert(
61e356f681SHui Xie     !std::is_assignable_v<std::expected<void, NotCopyAssignable>&, const std::unexpected<NotCopyAssignable>&>);
62e356f681SHui Xie 
63e356f681SHui Xie constexpr bool test() {
64e356f681SHui Xie   // - If has_value() is true, equivalent to:
65e356f681SHui Xie   //   construct_at(addressof(unex), std::forward<GF>(e.error()));
66e356f681SHui Xie   //   has_val = false;
67e356f681SHui Xie   {
68e356f681SHui Xie     Traced::state state{};
69e356f681SHui Xie     std::expected<void, Traced> e;
70e356f681SHui Xie     std::unexpected<Traced> un(std::in_place, state, 5);
71e356f681SHui Xie     decltype(auto) x = (e = un);
72e356f681SHui Xie     static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
73e356f681SHui Xie     assert(&x == &e);
74e356f681SHui Xie     assert(!e.has_value());
75e356f681SHui Xie     assert(e.error().data_ == 5);
76e356f681SHui Xie 
77e356f681SHui Xie     assert(state.copyCtorCalled);
78e356f681SHui Xie   }
79e356f681SHui Xie 
80e356f681SHui Xie   // - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
81e356f681SHui Xie   {
82e356f681SHui Xie     Traced::state state1{};
83e356f681SHui Xie     Traced::state state2{};
84e356f681SHui Xie     std::expected<void, Traced> e(std::unexpect, state1, 5);
85e356f681SHui Xie     std::unexpected<Traced> un(std::in_place, state2, 10);
86e356f681SHui Xie     decltype(auto) x = (e = un);
87e356f681SHui Xie     static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
88e356f681SHui Xie     assert(&x == &e);
89e356f681SHui Xie     assert(!e.has_value());
90e356f681SHui Xie     assert(e.error().data_ == 10);
91e356f681SHui Xie 
92e356f681SHui Xie     assert(state1.copyAssignCalled);
93e356f681SHui Xie   }
94e356f681SHui Xie 
954f469053SJan Kokemüller   // CheckForInvalidWrites
964f469053SJan Kokemüller   {
974f469053SJan Kokemüller     {
984f469053SJan Kokemüller       CheckForInvalidWrites<true, true> e;
994f469053SJan Kokemüller       std::unexpected<int> un(std::in_place, 42);
1004f469053SJan Kokemüller       e = un;
1014f469053SJan Kokemüller       assert(e.check());
1024f469053SJan Kokemüller     }
1034f469053SJan Kokemüller     {
1044f469053SJan Kokemüller       CheckForInvalidWrites<false, true> e;
1054f469053SJan Kokemüller       std::unexpected<bool> un(std::in_place, true);
1064f469053SJan Kokemüller       e = un;
1074f469053SJan Kokemüller       assert(e.check());
1084f469053SJan Kokemüller     }
1094f469053SJan Kokemüller   }
1104f469053SJan Kokemüller 
111e356f681SHui Xie   return true;
112e356f681SHui Xie }
113e356f681SHui Xie 
114e356f681SHui Xie void testException() {
115e356f681SHui Xie #ifndef TEST_HAS_NO_EXCEPTIONS
116e356f681SHui Xie   std::expected<void, ThrowOnCopyConstruct> e1(std::in_place);
117e356f681SHui Xie   std::unexpected<ThrowOnCopyConstruct> un(std::in_place);
118e356f681SHui Xie   try {
119e356f681SHui Xie     e1 = un;
120e356f681SHui Xie     assert(false);
121e356f681SHui Xie   } catch (Except) {
122e356f681SHui Xie     assert(e1.has_value());
123e356f681SHui Xie   }
124e356f681SHui Xie #endif // TEST_HAS_NO_EXCEPTIONS
125e356f681SHui Xie }
126e356f681SHui Xie 
127e356f681SHui Xie int main(int, char**) {
128e356f681SHui Xie   test();
129e356f681SHui Xie   static_assert(test());
130e356f681SHui Xie   testException();
131e356f681SHui Xie   return 0;
132e356f681SHui Xie }
133