1//===----------------------------------------------------------------------===//
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
8// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9
10// template<class G>
11// constexpr expected& operator=(const unexpected<G>& e);
12//
13// Let GF be const G&
14//
15// Constraints: is_constructible_v<E, GF> is true and is_assignable_v<E&, GF> is true.
16//
17// Effects:
18// - If has_value() is true, equivalent to:
19// construct_at(addressof(unex), std::forward<GF>(e.error()));
20// has_val = false;
21// - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
22//
23// Returns: *this.
24
25#include <cassert>
26#include <concepts>
27#include <expected>
28#include <type_traits>
29#include <utility>
30
31#include "../../types.h"
32#include "test_macros.h"
33
34struct NotCopyConstructible {
35 NotCopyConstructible(const NotCopyConstructible&) = delete;
36 NotCopyConstructible& operator=(const NotCopyConstructible&) = default;
37};
38
39struct NotCopyAssignable {
40 NotCopyAssignable(const NotCopyAssignable&) = default;
41 NotCopyAssignable& operator=(const NotCopyAssignable&) = delete;
42};
43
44struct MoveMayThrow {
45 MoveMayThrow(MoveMayThrow const&) = default;
46 MoveMayThrow& operator=(const MoveMayThrow&) = default;
47 MoveMayThrow(MoveMayThrow&&) noexcept(false) {}
48 MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) { return *this; }
49};
50
51// Test constraints
52static_assert(std::is_assignable_v<std::expected<void, int>&, const std::unexpected<int>&>);
53
54// !is_constructible_v<E, GF>
55static_assert(
56 !std::is_assignable_v<std::expected<void, NotCopyConstructible>&, const std::unexpected<NotCopyConstructible>&>);
57
58// !is_assignable_v<E&, GF>
59static_assert(
60 !std::is_assignable_v<std::expected<void, NotCopyAssignable>&, const std::unexpected<NotCopyAssignable>&>);
61
62constexpr bool test() {
63 // - If has_value() is true, equivalent to:
64 // construct_at(addressof(unex), std::forward<GF>(e.error()));
65 // has_val = false;
66 {
67 Traced::state state{};
68 std::expected<void, Traced> e;
69 std::unexpected<Traced> un(std::in_place, state, 5);
70 decltype(auto) x = (e = un);
71 static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
72 assert(&x == &e);
73 assert(!e.has_value());
74 assert(e.error().data_ == 5);
75
76 assert(state.copyCtorCalled);
77 }
78
79 // - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
80 {
81 Traced::state state1{};
82 Traced::state state2{};
83 std::expected<void, Traced> e(std::unexpect, state1, 5);
84 std::unexpected<Traced> un(std::in_place, state2, 10);
85 decltype(auto) x = (e = un);
86 static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
87 assert(&x == &e);
88 assert(!e.has_value());
89 assert(e.error().data_ == 10);
90
91 assert(state1.copyAssignCalled);
92 }
93
94 // CheckForInvalidWrites
95 {
96 {
97 CheckForInvalidWrites<true, true> e;
98 std::unexpected<int> un(std::in_place, 42);
99 e = un;
100 assert(e.check());
101 }
102 {
103 CheckForInvalidWrites<false, true> e;
104 std::unexpected<bool> un(std::in_place, true);
105 e = un;
106 assert(e.check());
107 }
108 }
109
110 return true;
111}
112
113void testException() {
114#ifndef TEST_HAS_NO_EXCEPTIONS
115 std::expected<void, ThrowOnCopyConstruct> e1(std::in_place);
116 std::unexpected<ThrowOnCopyConstruct> un(std::in_place);
117 try {
118 e1 = un;
119 assert(false);
120 } catch (Except) {
121 assert(e1.has_value());
122 }
123#endif // TEST_HAS_NO_EXCEPTIONS
124}
125
126int main(int, char**) {
127 test();
128 static_assert(test());
129 testException();
130 return 0;
131}
132

source code of libcxx/test/std/utilities/expected/expected.void/assign/assign.unexpected.copy.pass.cpp