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

来自cppreference.com
< cpp‎ | utility‎ | expected
 
 
工具库
语言支持
类型支持(基本类型、RTTI)
库功能特性测试宏 (C++20)
动态内存管理
程序工具
协程支持 (C++20)
变参数函数
调试支持
(C++26)
三路比较
(C++20)
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)   
(C++20)
交换类型运算
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
常用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
初等字符串转换
(C++17)
(C++17)

 
 
主模板
constexpr expected& operator=( const expected& other );
(1) (C++23 起)
constexpr expected& operator=( expected&& other ) noexcept(/* 见下文 */);
(2) (C++23 起)
template< class U = 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 partial specialization
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 对象赋予新值。

参数

other - 包含值要用来赋值的 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() 的值  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() 的值  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() 的值  等价于
true val = std::forward<U>(v);
false reinit-expected(val, unex, std::forward<U>(v));
has_val = false;
4,5) 按以下方式对非预期值进行赋值:
 重载   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() 的值  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() 的值  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() 的值  等价于
(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)
{
    // 情况 1:“new_val” 的构造不会抛出:
    // 在销毁 “old_val” 后可以直接构造 “new_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)...);
    }
    // 情况 2:“new_val” 的移动构造不会抛出:
    // 先构造一个临时的 NewType 对象
    // (如果该构造抛出异常,那么 “old_val” 不会受到影响)
    else if constexpr (std::is_nothrow_move_constructible_v<NewType>)
    {
        NewType temp(std::forward<Args>(args)...); // 可能会抛出异常
        std::destroy_at(std::addressof(old_val));
        std::construct_at(std::addressof(new_val), std::move(temp));
    }
    // 情况 3:“new_val” 的构造可能会抛出:
    // 需要备份 “old_val” 以从异常中恢复
    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)...); // 可能会抛出异常
        }
        catch (...)
        {
            std::construct_at(std::addressof(old_val), std::move(temp));
            throw;
        }
    }
}

当赋值会导致 *this 持有另一个预期种类的值时(即从持有预期值到持有非预期值,或从持有非预期值到持有预期值)时就会调用此函数模板。

此时在构造新值 newval 前需要先销毁旧值 oldval。然而构造 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 4025 C++23 E 不可移动构造或移动赋值时重载 (7) 会被定义为弃置 此时该重载不会参与重载决议

参阅

原位构造预期值
(公开成员函数)