名稱空間
變體
操作

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

來自 cppreference.com
< 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) 曾被定義為刪除的
在這種情況下它現在不參與
過載決議

[編輯] 參閱

就地構造所含的期望值
(公開成員函式) [編輯]