std::expected<T,E>::operator=
From cppreference.com
| プライマリテンプレート |
||
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()の値が異なる場合(つまり、*thisとotherのいずれかが期待値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) { // 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が代替値(つまり、期待値から期待値でない値へ、または期待値でない値から期待値へ)を持つようになる場合に呼び出されます。
この場合、新しい値newvalを構築する前に、古い値oldvalを破棄する必要があります。しかし、newvalの構築は例外をスローする可能性があります。強力な例外安全保証を提供するために、例外が再スローされる前に古い値を復元する必要があり、それにより、例外が処理されている間、*thisは有効な状態を持つようになります。
[編集] 戻り値
1-9) *this
[編集] 制約と補足情報
[編集] プライマリテンプレートの代入演算子
1) このオーバーロードは、以下のすべてがtrueである場合を除き、削除されます。
2) このオーバーロードは、以下のすべてがtrueである場合のみオーバーロード解決に参加します。
3) このオーバーロードは、以下のすべての条件が満たされている場合にのみ、オーバーロード解決に参加する。
- std::is_same_v<expected, std::remove_cvref_t<U>> が false であること。
- std::remove_cvref_t<U> が
std::unexpectedの特殊化でないこと。 - 以下のすべてがtrueであること。
4) このオーバーロードは、以下のすべてがtrueである場合のみオーバーロード解決に参加します。
- std::is_constructible_v<E, const G&>
- std::is_assignable_v<E&, const G&>
- std::is_nothrow_constructible_v<E, const G&> || std::is_nothrow_move_constructible_v<T> ||
std::is_nothrow_move_constructible_v<E>
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である場合のみオーバーロード解決に参加します。
[編集] 例外
2)
noexcept 指定:
noexcept(
std::is_nothrow_move_constructible_v<T> && std::is_nothrow_move_assignable_v<T> &&
7)
noexcept 指定:
noexcept(std::is_nothrow_move_constructible_v<E> && std::is_nothrow_move_assignable_v<E>)
[編集] 例
| このセクションは未完成です 理由: 例がありません |
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 3886 | C++23 | オーバーロード(3)のデフォルトテンプレート引数がTでした。 |
std::remove_cv_t<T>に変更されました。 |
| LWG 4025 | C++23 | オーバーロード(7)は、Eがムーブ構築可能またはムーブ代入可能でない |
場合に この場合、オーバーロード解決に参加しません。 |
[編集] 関連項目
| 期待値をインプレースで構築します。 (public member function) |