名前空間
変種
操作

std::variant<Types...>::operator=

提供: cppreference.com
< cpp‎ | utility‎ | variant
 
 
 
 
constexpr variant& operator=(const variant& rhs);
(1) (C++17以上)
constexpr variant& operator=(variant&& rhs) noexcept(/* see below */);
(2) (C++17以上)
template <class T> variant& operator=(T&& t) noexcept(/* see below */);
(3) (C++17以上)

新しい値を既存の variant オブジェクトに代入します。

1) コピー代入。
  • *thisrhs がどちらも valueless by exception であれば、何もしません。
  • そうでなく、 rhs が valueless だけれども *this がそうでなければ、 *this に格納されている値は破棄され、 valueless になります。
  • そうでなく、 rhs*this と同じ選択肢を保持していれば、 rhs に格納されている値が *this に格納されている値に代入されます。 例外が投げられた場合、 *this は valueless になりません。 値はその選択肢のコピー代入の例外安全性保証によります。
  • そうでなく、 rhs の保持している選択肢が無例外コピー構築可能であるか無例外ムーブ構築可能で「ない」かのいずれかであれば (それぞれ std::is_nothrow_copy_constructible および std::is_nothrow_move_constructible によって判定されます)、 this->emplace<rhs.index()>(get<rhs.index()>(rhs)) と同等です。
  • そうでなければ、 this->operator=(variant(rhs)) と同等です。 (2) で説明しているように、 *thisvalueless_by_exception になるかもしれないことに注意してください。
このオーバーロードは、 Types... 内のすべての T_i について std::is_copy_constructible_v<T_i>std::is_copy_assignable_v<T_i> がどちらも true でなければ、削除されたものとして定義されます。 このオーバーロードは、 Types... 内のすべての T_i について std::is_trivially_copy_constructible_v<T_i>std::is_trivially_copy_assignable_v<T_i> および std::is_trivially_destructible_v<T_i> がすべて true であれば、トリビアルです。
2) ムーブ代入。
  • *thisrhs がどちらも valueless by exception であれば、何もしません。
  • そうでなく、 rhs が valueless だけれども *this がそうでなければ、 *this に格納されている値は破棄され、 valueless になります。
  • そうでなく、 rhs*this と同じ選択肢を保持していれば、 std::get<j>(std::move(rhs))*this に格納されている値に代入されます。 ただし jindex() です。 例外が投げられた場合、 *this は valueless になりません。 値はその選択肢のムーブ代入の例外安全性保証によります。
  • そうでなければ (rhs*this が異なる選択肢を保持している場合)、 this->emplace<rhs.index()>(get<rhs.index()>(std::move(rhs))) と同等です。 T_i のムーブコンストラクタによって例外が投げられた場合、 *thisvalueless_by_exception になります。
このオーバーロードは、Types... 内のすべての T_i について std::is_move_constructible_v<T_i>std::is_move_assignable_v<T_i> がどちらも true である場合にのみ、オーバーロード解決に参加します。 このオーバーロードは、 Types... 内のすべての T_i について std::is_trivially_move_constructible_v<T_i>std::is_trivially_move_assignable_v<T_i> および std::is_trivially_destructible_v<T_i> がすべて true であれば、トリビアルです。
3) 変換代入。
  • そのときのスコープにおいて Types... のすべての T_i に対して架空の関数 F(T_i) のオーバーロードが存在した場合に式 F(std::forward<T>(t)) に対するオーバーロード解決によって選択されるであろう選択肢の型 T_j を決定します。
  • *this がすでに T_j を保持していれば、 std::forward<T>(t)*this に格納されている値に代入されます。 例外が投げられた場合、 *this は valueless になりません。 値は呼ばれた代入の例外安全性保証によります。
  • そうでなく、 std::is_nothrow_constructible_v<T_j, T> || !std::is_nothrow_move_constructible_v<T_j>true であれば、 this->emplace<j>(std::forward<T>(t)) と同等です。
  • そうでなければ、 this->operator=(variant(std::forward<T>(t))) と同等です。

このオーバーロードは、std::decay_t<T> (C++20未満)std::remove_cvref_t<T> (C++20以上)variant と同じ型でなく、 std::is_assignable_v<T_j&, T> が true であり、 std::is_constructible_v<T_j, T> が true であり、式 F(std::forward<T>(t)) (ただし F は前述の架空の関数のオーバーロード集合です) が well-formed である場合にのみ、オーバーロード解決に参加します。

std::variant<string> v1;
v1 = "abc"; // OK
std::variant<std::string, std::string> v2;
v2 = "abc"; // エラー
std::variant <std::string, bool> v3;
v3 = "abc"; // OK、 string が選択されます。 bool は候補ではありません。
std::variant<float, long, double> v4; // float 保持します。
v4 = 0; // OK、 long を保持します。 float および double は候補ではありません。

目次

[編集] 引数

rhs - 別の variant
t - variant の選択肢のいずれかに変換可能な値

[編集] 戻り値

*this

[編集] 例外

1) あらゆる選択肢の代入、コピーおよびムーブ初期化によって投げられるあらゆる例外が投げられる可能性があります。
2)
noexcept 指定:  
3)

[編集]

[編集] 欠陥報告

以下の動作変更欠陥報告は以前に発行された C++ 標準に遡って適用されました。

DR 適用先 発行時の動作 正しい動作
LWG 3024 C++17 copy assignment operator doesn't participate in overload resolution if any member type is not copyable defined as deleted instead
P0602R4 C++17 copy/move assignment may not be trivial even if underlying operations are trivial required to propagate triviality
P0608R3 C++17 converting assignment blindly assembles an overload set, leading to unintended conversions narrowing and boolean conversions not considered

[編集] 関連項目

variant 内の値をその場で構築します
(パブリックメンバ関数) [edit]