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