22 General utilities library [utilities]

22.8 Expected objects [expected]

22.8.6 Class template expected [expected.expected]

22.8.6.4 Assignment [expected.object.assign]

This subclause makes use of the following exposition-only function: template<class T, class U, class... Args> constexpr void reinit-expected(T& newval, U& oldval, Args&&... args) { // exposition only if constexpr (is_nothrow_constructible_v<T, Args...>) { destroy_at(addressof(oldval)); construct_at(addressof(newval), std::forward<Args>(args)...); } else if constexpr (is_nothrow_move_constructible_v<T>) { T tmp(std::forward<Args>(args)...); destroy_at(addressof(oldval)); construct_at(addressof(newval), std::move(tmp)); } else { U tmp(std::move(oldval)); destroy_at(addressof(oldval)); try { construct_at(addressof(newval), std::forward<Args>(args)...); } catch (...) { construct_at(addressof(oldval), std::move(tmp)); throw; } } }
constexpr expected& operator=(const expected& rhs);
Effects:
  • If this->has_­value() && rhs.has_­value() is true, equivalent to val = *rhs.
  • Otherwise, if this->has_­value() is true, equivalent to: reinit-expected(unex, val, rhs.error())
  • Otherwise, if rhs.has_­value() is true, equivalent to: reinit-expected(val, unex, *rhs)
  • Otherwise, equivalent to unex = rhs.error().
Then, if no exception was thrown, equivalent to: has_­val = rhs.has_­value(); return *this;
Remarks: This operator is defined as deleted unless:
  • is_­copy_­assignable_­v<T> is true and
  • is_­copy_­constructible_­v<T> is true and
  • is_­copy_­assignable_­v<E> is true and
  • is_­copy_­constructible_­v<E> is true and
  • is_­nothrow_­move_­constructible_­v<T> || is_­nothrow_­move_­constructible_­v<E> is true.
constexpr expected& operator=(expected&& rhs) noexcept(see below);
Constraints:
  • is_­move_­constructible_­v<T> is true and
  • is_­move_­assignable_­v<T> is true and
  • is_­move_­constructible_­v<E> is true and
  • is_­move_­assignable_­v<E> is true and
  • is_­nothrow_­move_­constructible_­v<T> || is_­nothrow_­move_­constructible_­v<E> is true.
Effects:
  • If this->has_­value() && rhs.has_­value() is true, equivalent to val = std​::​move(*rhs).
  • Otherwise, if this->has_­value() is true, equivalent to: reinit-expected(unex, val, std::move(rhs.error()))
  • Otherwise, if rhs.has_­value() is true, equivalent to: reinit-expected(val, unex, std::move(*rhs))
  • Otherwise, equivalent to unex = std​::​move(rhs.error()).
Then, if no exception was thrown, equivalent to: has_­val = rhs.has_­value(); return *this;
Remarks: The exception specification is equivalent to: is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<E> && is_nothrow_move_constructible_v<E>
template<class U = T> constexpr expected& operator=(U&& v);
Constraints:
  • is_­same_­v<expected, remove_­cvref_­t<U>> is false; and
  • remove_­cvref_­t<U> is not a specialization of unexpected; and
  • is_­constructible_­v<T, U> is true; and
  • is_­assignable_­v<T&, U> is true; and
  • is_­nothrow_­constructible_­v<T, U> || is_­nothrow_­move_­constructible_­v<T> ||
    is_­nothrow_­move_­constructible_­v<E>
    is true.
Effects:
  • If has_­value() is true, equivalent to: val = std​::​forward<U>(v);
  • Otherwise, equivalent to: reinit-expected(val, unex, std::forward<U>(v)); has_val = true;
Returns: *this.
template<class G> constexpr expected& operator=(const unexpected<G>& e); template<class G> constexpr expected& operator=(unexpected<G>&& e);
Let GF be const G& for the first overload and G for the second overload.
Constraints:
  • is_­constructible_­v<E, GF> is true; and
  • is_­assignable_­v<E&, GF> is true; and
  • is_­nothrow_­constructible_­v<E, GF> || is_­nothrow_­move_­constructible_­v<T> ||
    is_­nothrow_­move_­constructible_­v<E>
    is true.
Effects:
  • If has_­value() is true, equivalent to: reinit-expected(unex, val, std::forward<GF>(e.value())); has_val = false;
  • Otherwise, equivalent to: unex = std​::​forward<GF>(e.value());
Returns: *this.
template<class... Args> constexpr T& emplace(Args&&... args) noexcept;
Constraints: is_­nothrow_­constructible_­v<T, Args...> is true.
Effects: Equivalent to: if (has_value()) { destroy_at(addressof(val)); } else { destroy_at(addressof(unex)); has_val = true; } return *construct_at(addressof(val), std::forward<Args>(args)...);
template<class U, class... Args> constexpr T& emplace(initializer_list<U> il, Args&&... args) noexcept;
Constraints: is_­nothrow_­constructible_­v<T, initializer_­list<U>&, Args...> is true.
Effects: Equivalent to: if (has_value()) { destroy_at(addressof(val)); } else { destroy_at(addressof(unex)); has_val = true; } return *construct_at(addressof(val), il, std::forward<Args>(args)...);