Spec-Zone.ru › C++

std::expected<T,E>::operator=

constexpr expected& operator=( const expected& other );
(1) (начиная с C++23)
constexpr expected& operator=( expected&& other ) noexcept(/*see below*/);
(2) (начиная с C++23)
template< class U = std::remove_cv_t<T> >
constexpr expected& operator=( U&& v );
(3) (начиная с C++23)
(T не является cv void)
template< class G >
constexpr expected& operator=( const unexpected<G>& other );
(4) (начиная с C++23)
template< class G >
constexpr expected& operator=( unexpected<G>&& other );
(5) (начиная с C++23)

Присваивает новое значение существующему объекту expected.

1,2) Присваивает состояние other.
  • Если this->has_value() равно other.has_value(), присваивает значение, содержащееся в other. Ничего не делает, если T является (возможно, cv-квалифицированным) void, а other.has_value() равно true.
  • В противном случае уничтожает текущее содержащееся значение (ничего не делает, если this->has_value() равно true, а T является (возможно, cv-квалифицированным) void) и заставляет *this содержать копию значения, содержащегося в other.
Если other.has_value() равно true, а T является (возможно, cv-квалифицированным) void, новое значение не конструируется. В противном случае новое значение копирующе конструируется (1) или перемещающе конструируется (2) из *other или other.error(), в зависимости от ситуации. Если выбрасывается исключение, старое значение сохраняется; *this не становится не содержащим значения.

Если исключение не было выброшено, после присваивания has_value() равно other.has_value().

  • Перегрузка (1) определяется как удалённая, если не выполняются следующие условия:
    • либо T является (возможно, cv-квалифицированным) void, либо std::is_copy_assignable_v<T> равно true, и
    • либо T является (возможно, cv-квалифицированным) void, либо std::is_copy_constructible_v<T> равно true, и
    • std::is_copy_assignable_v<E> равно true, и
    • std::is_copy_constructible_v<E> равно true, и
    • хотя бы одно из следующих условий истинно (true):
      • T является (возможно, cv-квалифицированным) void
      • std::is_nothrow_move_constructible_v<T>
      • std::is_nothrow_move_constructible_v<E>
  • Перегрузка (2) участвует в разрешении перегрузки, только если
    • либо T является (возможно, cv-квалифицированным) void, либо std::is_move_assignable_v<T> равно true, и
    • либо T является (возможно, cv-квалифицированным) void, либо std::is_move_constructible_v<T> равно true, и
    • std::is_move_assignable_v<E> равно true, и
    • std::is_move_constructible_v<E> равно true, и
    • хотя бы одно из следующих условий истинно (true):
      • T является (возможно, cv-квалифицированным) void
      • std::is_nothrow_move_constructible_v<T>
      • std::is_nothrow_move_constructible_v<E>
3) Присваивает значение expected.
  • Если this->has_value() равно true, эквивалентно **this = std::forward<U>(v).
  • В противном случае уничтожает значение, содержащееся в *this, и заставляет *this содержать значение, инициализированное из std::forward<U>(v). Если выбрасывается исключение, старое значение сохраняется; *this не становится не содержащим значения.

Если исключение не было выброшено, после присваивания this->has_value() равно true.

  • Эта перегрузка участвует в разрешении перегрузки, только если
    • std::is_same_v<expected, std::remove_cvref_t<U>> равно false, и
    • std::remove_cvref_t<U> не является специализацией std::unexpected, и
    • std::is_constructible_v<T, U> равно true, и
    • std::is_assignable_v<T&, U> равно true, и
    • хотя бы одно из следующих условий истинно (true):
      • std::is_nothrow_constructible_v<T, U>
      • std::is_nothrow_move_constructible_v<T>
      • std::is_nothrow_move_constructible_v<E>
4,5) Присваивает значение unexpected.

Пусть GF обозначает const G& для перегрузки (4), а G — для перегрузки (5).

  • Если this->has_value() равно true, уничтожает значение, содержащееся в *this (ничего не делает, если T является (возможно, cv-квалифицированным) void), и заставляет *this содержать значение, инициализированное из std::forward<GF>(e.error()). Если выбрасывается исключение, старое значение сохраняется; *this не становится не содержащим значения.
  • В противном случае эквивалентно this->error() = std::forward<GF>(e.error()).

Если исключение не было выброшено, после присваивания this->has_value() равно false.

  • Эта перегрузка участвует в разрешении перегрузки, только если
    • std::is_constructible_v<E, GF> равно true, и
    • std::is_assignable_v<E&, GF> равно true, и
    • хотя бы одно из следующих условий истинно (true):
      • T является (возможно, cv-квалифицированным) void
      • std::is_nothrow_constructible_v<E, GF>
      • std::is_nothrow_move_constructible_v<T>
      • std::is_nothrow_move_constructible_v<E>


Во всех случаях, если T не является (возможно, cv-квалифицированным) void, уничтожение старого значения и конструирование нового выполняются так, как если бы использовалась следующая функция, предназначенная только для изложения: reinit_expected.

template<class NewType, class OldType, class... Args>
constexpr void reinit_expected(NewType& new_val, OldType& old_val, Args&&... args)
{
    if constexpr (std::is_nothrow_constructible_v<NewType, Args...>)
    {
        std::destroy_at(std::addressof(old_val));
        std::construct_at(std::addressof(new_val), std::forward<Args>(args)...);
    }
    else if constexpr (std::is_nothrow_move_constructible_v<NewType>)
    {
        NewType temp(std::forward<Args>(args)...); // may throw
        std::destroy_at(std::addressof(old_val));
        std::construct_at(std::addressof(new_val), std::move(temp));
    }
    else
    {
        OldType temp(std::move(old_val));
        std::destroy_at(std::addressof(old_val));
        try
        {
            std::construct_at(std::addressof(new_val), std::forward<Args>(args)...); // may throw
        }
        catch (...)
        {
            std::construct_at(std::addressof(old_val), std::move(temp));
            throw;
        }
    }
}

Параметры

other - другой объект expected, значение которого требуется присвоить
value - значение, присваиваемое содержащемуся значению
e - объект std::unexpected, значение которого требуется присвоить

Возвращаемое значение

*this

Исключения

1) Выбрасывает любое исключение, выброшенное конструктором копирования или оператором копирующего присваивания T или E.
2) Если T является (возможно, cv-квалифицированным) void,
noexcept спецификация:
noexcept(std::is_nothrow_move_constructible_v<E> && std::is_nothrow_move_assignable_v<E>)
В противном случае
noexcept спецификация:
noexcept(
    std::is_nothrow_move_constructible_v<T> && std::is_nothrow_move_assignable_v<T> &&
    std::is_nothrow_move_constructible_v<E> && std::is_nothrow_move_assignable_v<E>)
3) Выбрасывает любое исключение, выброшенное конструктором или оператором присваивания T.
4,5) Выбрасывает любое исключение, выброшенное конструктором или оператором присваивания E.

Пример

Отчёты об ошибках

Следующие отчёты об ошибках, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.

Отчёт об ошибке Применён к Опубликованное поведение Корректное поведение
LWG 3886 C++23 аргумент шаблона по умолчанию перегрузки (3) был T изменён на std::remove_cv_t<T>
LWG 4025 C++23 перемещающее присваивание (2) для std::expected<void, E>
определялось как удалённое, если E не поддерживает перемещающее конструирование или перемещающее присваивание
в этом случае оно не участвует
в разрешении перегрузки

См. также

emplace
конструирует значение expected на месте
(открытая функция-член)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/utility/expected/operator%3D

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API