147 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// 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 32struct NotCopyConstructible {33 NotCopyConstructible(const NotCopyConstructible&) = delete;34 NotCopyConstructible& operator=(const NotCopyConstructible&) = default;35};36 37struct NotCopyAssignable {38 NotCopyAssignable(const NotCopyAssignable&) = default;39 NotCopyAssignable& operator=(const NotCopyAssignable&) = delete;40};41 42// Test constraints43static_assert(std::is_copy_assignable_v<std::expected<void, int>>);44 45// !is_copy_assignable_v<E>46static_assert(!std::is_copy_assignable_v<std::expected<void, NotCopyAssignable>>);47 48// !is_copy_constructible_v<E>49static_assert(!std::is_copy_assignable_v<std::expected<void, NotCopyConstructible>>);50 51constexpr 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 // CheckForInvalidWrites104 {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 128void testException() {129#ifndef TEST_HAS_NO_EXCEPTIONS130 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_EXCEPTIONS139}140 141int main(int, char**) {142 test();143 static_assert(test());144 testException();145 return 0;146}147