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