命名空间
变体
操作

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

来自 cppreference.cn
< cpp‎ | 工具库‎ | expected
 
 
 
 
主模板
constexpr expected& operator=( const expected& other );
(1) (C++23 起)
constexpr expected& operator=( expected&& other )
    noexcept(/* 见下方 */);
(2) (C++23 起)
template< class U = std::remove_cv_t<T> >
constexpr expected& operator=( U&& v );
(3) (C++23 起)
template< class G >
constexpr expected& operator=( const std::unexpected<G>& e );
(4) (C++23 起)
template< class G >
constexpr expected& operator=( std::unexpected<G>&& e );
(5) (C++23 起)
void 偏特化
constexpr expected& operator=( const expected& other );
(6) (C++23 起)
constexpr expected& operator=( expected&& other )
    noexcept(/* 见下方 */);
(7) (C++23 起)
template< class G >
constexpr expected& operator=( const std::unexpected<G>& e );
(8) (C++23 起)
template< class G >
constexpr expected& operator=( std::unexpected<G>&& e );
(9) (C++23 起)
辅助函数模板
template< class T, class U, class... Args >
constexpr void reinit-expected( T& newval, U& oldval, Args&&... args )
(10) (C++23 起)
(仅作说明*)

给一个已存在的 expected 对象赋新值。

目录

[编辑] 参数

其他 - 另一个 expected 对象,将其所含的值赋给当前对象
v - 要赋值给包含值的值
e - std::unexpected 对象,将其所含的值赋给当前对象
newval - 要构造的所含值
oldval - 要销毁的所含值
args - 用作 newval 初始化的参数

[编辑] 效果

[编辑] 主模板赋值运算符

1,2)other 的状态赋给 *this
如果 has_value()rhs.has_value() 的值不同(即 *thisother 中一个含有期望值 val,而另一个含有非期望值 unex ),则调用仅用于阐释的函数模板 reinit-expected 来安全地更新状态。
1) 所含值的赋值方式如下
has_value() 的值
 has_value() 的值 
other.has_value() 的值
true false
true val = *other; reinit-expected
    (unex, val, other.error());
false reinit-expected
    (val, unex, *other);
unex = other.error();
2) 所含值的赋值方式如下
has_value() 的值
 has_value() 的值 
other.has_value() 的值
true false
true val = std::move(*other); reinit-expected
    (unex, val, std::move(other.error()));
false reinit-expected
    (val, unex,
     std::move(*other));
unex = std::move(other.error());
然后,若未抛出异常,则执行 has_val = other.has_value();
3) 期望值的赋值方式如下
has_value() 的值
 has_value() 的值 
等价于
true val = std::forward<U>(v);
false reinit-expected(val, unex, std::forward<U>(v));
has_val = false;
4,5) 非期望值的赋值方式如下
 重载  has_value() 的值
 has_value() 的值 
等价于
(4) true reinit-expected(val, unex, std::forward<const G&>(e.error()));
has_val = false;
false unex = std::forward<const G&>(e.error());
(5) true reinit-expected(val, unex, std::forward<G>(e.error()));
has_val = false;
false unex = std::forward<G>(e.error());

[编辑] void 部分特化赋值运算符

6) 非期望值的赋值或销毁方式如下
has_value() 的值
 has_value() 的值 
other.has_value() 的值
true false
true (无效果) std::construct_at
    (std::addressof(unex), rhs.unex);
has_val = false;
false std::destroy_at(std::addressof(unex));
has_val = true;
unex = other.error();
7) 非期望值的赋值或销毁方式如下
has_value() 的值
 has_value() 的值 
other.has_value() 的值
true false
true (无效果) std::construct_at
    (std::addressof(unex),
     std::move(rhs.unex));
has_val = false;
false std::destroy_at(std::addressof(unex));
has_val = true;
unex = std::move(other.error());
8,9) 非期望值的赋值方式如下
 重载  has_value() 的值
 has_value() 的值 
等价于
(8) true std::construct_at(std::addressof(unex),
                  std::forward<const G&>(e.error()));
has_val = false;
false unex = std::forward<const G&>(e.error());
(9) true std::construct_at(std::addressof(unex), std::forward<G>(e.error()));
has_val = false;
false unex = std::forward<G>(e.error());

[编辑] 辅助函数模板

仅用于阐释的函数模板 reinit-expected “定义”如下

template<class NewType, class OldType, class... Args>
constexpr void reinit-expected(NewType& new_val, OldType& old_val, Args&&... args)
{
    // Case 1: the construction of “new_val” is non-throwing:
    // “new_val” can be directly constructed after destroying “old_val”
    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)...);
    }
    // Case 2: the move construction of “new_val” is non-throwing:
    // constuct a temporary NewType object first
    // (“old_val” is left intact if an exception is thrown from this construction)
    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));
    }
    // Case 3: the construction of “new_val” is potentially-throwing:
    // a backup of “old_val” is required in order to recover from an exception
    else
    {
        OldType temp(std::move(old_val)); // may throw
        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;
        }
    }
}

当赋值操作将使 *this 持有备选值时(即从期望值变为非期望值,或从非期望值变为期望值),会调用此函数模板。

在这种情况下,旧值 oldval 需要在构造新值 newval 之前被销毁。然而,newval 的构造可能会抛出异常。为了提供强异常安全保证,在重新抛出异常之前需要恢复旧值,以便在处理异常时 *this 仍处于有效状态。

[编辑] 返回值

1-9) *this

[编辑] 约束和补充信息

[编辑] 主模板赋值运算符

3) 此重载仅在满足以下所有条件时才参与重载决议
4) 仅若以下所有条件均为 true,此重载才会参与重载决议
5) 仅若以下所有条件均为 true,此重载才会参与重载决议

[编辑] void 部分特化赋值运算符

6) 除非 std::is_copy_assignable_v<E>std::is_copy_constructible_v<E> 均为 true,否则此重载被定义为删除的。
7) 仅若 std::is_move_constructible_v<E>std::is_move_assignable_v<E> 均为 true,此重载才会参与重载决议。
8) 仅若 std::is_constructible_v<E, const G&>std::is_assignable_v<E&, const G&> 均为 true,此重载才会参与重载决议。
9) 仅若 std::is_constructible_v<E, G>std::is_assignable_v<E&, G> 均为 true,此重载才会参与重载决议。

[编辑] 异常

[编辑] 示例

[编辑] 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 发布时的行为 正确的行为
LWG 3886 C++23 重载 (3) 的默认模板实参曾为 T 改为 std::remove_cv_t<T>
LWG 4025 C++23 E 不可移动构造或不可移动赋值,
重载 (7) 曾被定义为删除的
在这种情况下它现在不参与
重载决议

[编辑] 参阅

就地构造所含的期望值
(公开成员函数) [编辑]