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++03, c++11, c++14, c++17, c++20 10 11 // constexpr expected& operator=(const expected& rhs); 12 // 13 // Effects: 14 // - If this->has_value() && rhs.has_value() is true, no effects. 15 // - Otherwise, if this->has_value() is true, equivalent to: construct_at(addressof(unex), rhs.unex); has_val = false; 16 // - Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true. 17 // - Otherwise, equivalent to unex = rhs.error(). 18 // 19 // Returns: *this. 20 // 21 // Remarks: This operator is defined as deleted unless is_copy_assignable_v<E> is true and is_copy_constructible_v<E> is true. 22 23 #include <cassert> 24 #include <concepts> 25 #include <expected> 26 #include <type_traits> 27 #include <utility> 28 29 #include "../../types.h" 30 #include "test_macros.h" 31 32 struct NotCopyConstructible { 33 NotCopyConstructible(const NotCopyConstructible&) = delete; 34 NotCopyConstructible& operator=(const NotCopyConstructible&) = default; 35 }; 36 37 struct NotCopyAssignable { 38 NotCopyAssignable(const NotCopyAssignable&) = default; 39 NotCopyAssignable& operator=(const NotCopyAssignable&) = delete; 40 }; 41 42 // Test constraints 43 static_assert(std::is_copy_assignable_v<std::expected<void, int>>); 44 45 // !is_copy_assignable_v<E> 46 static_assert(!std::is_copy_assignable_v<std::expected<void, NotCopyAssignable>>); 47 48 // !is_copy_constructible_v<E> 49 static_assert(!std::is_copy_assignable_v<std::expected<void, NotCopyConstructible>>); 50 51 constexpr bool test() { 52 // If this->has_value() && rhs.has_value() is true, no effects. 53 { 54 std::expected<void, int> e1; 55 std::expected<void, int> e2; 56 decltype(auto) x = (e1 = e2); 57 static_assert(std::same_as<decltype(x), std::expected<void, int>&>); 58 assert(&x == &e1); 59 assert(e1.has_value()); 60 } 61 62 // Otherwise, if this->has_value() is true, equivalent to: construct_at(addressof(unex), rhs.unex); has_val = false; 63 { 64 Traced::state state{}; 65 std::expected<void, Traced> e1; 66 std::expected<void, Traced> e2(std::unexpect, state, 5); 67 decltype(auto) x = (e1 = e2); 68 static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>); 69 assert(&x == &e1); 70 assert(!e1.has_value()); 71 assert(e1.error().data_ == 5); 72 73 assert(state.copyCtorCalled); 74 } 75 76 // Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true. 77 { 78 Traced::state state{}; 79 std::expected<void, Traced> e1(std::unexpect, state, 5); 80 std::expected<void, Traced> e2; 81 decltype(auto) x = (e1 = e2); 82 static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>); 83 assert(&x == &e1); 84 assert(e1.has_value()); 85 86 assert(state.dtorCalled); 87 } 88 89 // Otherwise, equivalent to unex = rhs.error(). 90 { 91 Traced::state state{}; 92 std::expected<void, Traced> e1(std::unexpect, state, 5); 93 std::expected<void, Traced> e2(std::unexpect, state, 10); 94 decltype(auto) x = (e1 = e2); 95 static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>); 96 assert(&x == &e1); 97 assert(!e1.has_value()); 98 assert(e1.error().data_ == 10); 99 100 assert(state.copyAssignCalled); 101 } 102 103 // CheckForInvalidWrites 104 { 105 { 106 CheckForInvalidWrites<true, true> e1; 107 CheckForInvalidWrites<true, true> e2(std::unexpect); 108 109 e1 = e2; 110 111 assert(e1.check()); 112 assert(e2.check()); 113 } 114 { 115 CheckForInvalidWrites<false, true> e1; 116 CheckForInvalidWrites<false, true> e2(std::unexpect); 117 118 e1 = e2; 119 120 assert(e1.check()); 121 assert(e2.check()); 122 } 123 } 124 125 return true; 126 } 127 128 void testException() { 129 #ifndef TEST_HAS_NO_EXCEPTIONS 130 std::expected<void, ThrowOnCopyConstruct> e1(std::in_place); 131 std::expected<void, ThrowOnCopyConstruct> e2(std::unexpect); 132 try { 133 e1 = e2; 134 assert(false); 135 } catch (Except) { 136 assert(e1.has_value()); 137 } 138 #endif // TEST_HAS_NO_EXCEPTIONS 139 } 140 141 int main(int, char**) { 142 test(); 143 static_assert(test()); 144 testException(); 145 return 0; 146 } 147