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