std::variant<Types...>::variant
提供: cppreference.com
<tbody>
</tbody>
constexpr variant() noexcept(/* see below */); |
(1) | (C++17以上) |
constexpr variant(const variant& other); |
(2) | (C++17以上) |
constexpr variant(variant&& other) noexcept(/* see below */); |
(3) | (C++17以上) |
template< class T > constexpr variant(T&& t) noexcept(/* see below */); |
(4) | (C++17以上) |
template< class T, class... Args > constexpr explicit variant(std::in_place_type_t<T>, Args&&... args); |
(5) | (C++17以上) |
template< class T, class U, class... Args > constexpr explicit variant(std::in_place_type_t<T>, std::initializer_list<U> il, Args&&... args); |
(6) | (C++17以上) |
template< std::size_t I, class... Args > constexpr explicit variant(std::in_place_index_t<I>, Args&&... args); |
(7) | (C++17以上) |
template< std::size_t I, class U, class... Args > constexpr explicit variant(std::in_place_index_t<I>, std::initializer_list<U> il, Args&&... args); |
(8) | (C++17以上) |
新しい variant オブジェクトを構築します。
1) デフォルトコンストラクタ。 最初の選択肢 (index() がゼロ) の値初期化された値を保持する variant を構築します。 選択肢の型 T_0 の値初期化が constexpr 関数の要件を満たす場合、このコンストラクタは
constexpr になります。 このオーバーロードは、std::is_default_constructible_v<T_0> が true である場合にのみ、オーバーロード解決に参加します。2) コピーコンストラクタ。
other が valueless_by_exception でなければ、 other と同じ選択肢を保持する variant を構築し、格納される値を std::get<other.index()>(other) で直接初期化します。 そうでなければ、 valueless_by_exception な variant を初期化します。 Types... 内のすべての T_i について std::is_copy_constructible_v<T_i> が true でなければ、このコンストラクタは削除されたものとして定義されます。 Types... 内のすべての T_i について std::is_trivially_copy_constructible_v<T_i> が true であれば、このコンストラクタはトリビアルです。3) ムーブコンストラクタ。
other が valueless_by_exception でなければ、 other と同じ選択肢を保持する variant を構築し、格納される値を std::get<other.index()>(std::move(other)) で 直接初期化します。 そうでなければ、 valueless_by_exception な variant 初期化します。 このオーバーロードは、 Types... 内のすべての T_i について std::is_move_constructible_v<T_i> が true である場合にのみ、オーバーロード解決に参加します。 Types... 内のすべての T_i について std::is_trivially_move_constructible_v<T_i> が true であれば、このコンストラクタはトリビアルです。4) 変換コンストラクタ。 そのときのスコープにおいて
Types... のすべての T_i に対して架空の関数 F(T_i) のオーバーロードが存在した場合に式 F(std::forward<T>(t)) に対するオーバーロード解決によって選択されるであろう型 T_j を保持する variant を構築します。 ただし、
- オーバーロード
F(T_i)は何らかの架空の変数xについて宣言T_i x[] = { std::forward<T>(t) };が有効な場合にのみ 考慮されます。 T_iがbool(cv 修飾されていても構いません) の場合、F(T_i)はstd:remove_cvref_t<T>もまたboolである場合にのみ考慮されます。
- オーバーロード
格納される値は、
std::forward<T>(t) から直接非リスト初期化されたかのように、直接初期化されます。 このオーバーロードは、 sizeof...(Types) > 0 であり、 std::decay_t<U> (C++20未満)std::remove_cvref_t<U> (C++20以上) が variant と同じ型でも std::in_place_type_t の特殊化でも std::in_place_index_t の特殊化でもなく、 std::is_constructible_v<T_j, T> が true であり、式 F(std::forward<T>(t)) (ただし F は前述の架空の関数のオーバーロード集合です) が well-formed である場合にのみ、オーバーロード解決に参加します。 T_j の選択されたコンストラクタが constexpr コンストラクタであれば、このコンストラクタも constexpr コンストラクタになります。
std::variant<std::string> v("abc"); // OK
std::variant<std::string, std::string> w("abc"); // ill-formed
std::variant<std::string, const char*> x("abc"); // OK、 const char* が選択されます。
std::variant<std::string, bool> y("abc"); // OK、 string が選択されます。 bool は候補ではありません。
std::variant<float, long, double> z = 0; // OK、 long を保持します。
// float と double は候補ではありません。
5) 指定された選択肢
T の variant を構築し、格納される値を引数 std::forward<Args>(args)... で初期化します。 T の選択されたコンストラクタが constexpr コンストラクタであれば、このコンストラクタも constexpr コンストラクタになります。 このオーバーロードは、Types... 内に T がちょうど1回だけ現れ、 std::is_constructible_v<T, Args...> が true である場合にのみ、オーバーロード解決に参加します。6) 指定された選択肢
T で variant を構築し、格納される値を引数 il, std::forward<Args>(args)... で初期化します。 T の選択されたコンストラクタが constexpr コンストラクタであれば、このコンストラクタも constexpr コンストラクタになります。 このオーバーロードは、Types... 内に T がちょうど1回だけ現れ、 std::is_constructible_v<T, initializer_list<U>&, Args...> が true である場合にのみ、オーバーロード解決に参加します。7) インデックス
I で指定された選択肢 T_i で variant を構築し、格納される値を引数 std::forward<Args>(args)... で初期化します。 T_i の選択されたコンストラクタが constexpr コンストラクタであれば、このコンストラクタも constexpr コンストラクタになります。 このオーバーロードは、I < sizeof...(Types) であり、 std::is_constructible_v<T_i, Args...> が true である場合にのみ、オーバーロード解決に参加します。8) インデックス
I で指定された選択肢 T_i で variant を構築し、格納される値を引数 il, std::forward<Args>(args)... で初期化します。 T_i の選択されたコンストラクタが constexpr であれば、このコンストラクタも constexpr コンストラクタになります。 このオーバーロードは、I < sizeof...(Types) であり、 std::is_constructible_v<T_i, std::initializer_list<U>&, Args...> が true である場合にのみ、オーバーロード解決に参加します。引数
| other | - | 格納されている値をコピーまたはムーブする別の variant オブジェクト
|
| t | - | 格納される値を初期化するための値 |
| args... | - | 格納される値を初期化するための引数 |
| il | - | 格納される値を初期化するための初期化子リスト |
例外
1) 最初の選択肢の値初期化によって投げられるあらゆる例外を投げる可能性があります。
noexcept 指定:
noexcept(std::is_nothrow_default_constructible_v<T_0>)2)
Types... 内のあらゆる T_i の直接初期化によって投げられるあらゆる例外を投げる可能性があります。3)
Types... 内のあらゆる T_i のムーブ構築によって投げられるあらゆる例外を投げる可能性があります。noexcept 指定:
noexcept( (std::is_nothrow_move_constructible_v<Types> && ...))4) 選択された選択肢
T_j の初期化によって投げられるあらゆる例外を投げる可能性があります。noexcept 指定:
noexcept(std::is_nothrow_constructible_v<T_j, T>)5-8) 選択された選択肢の選択されたコンストラクタを呼ぶことによって投げられるあらゆる例外を投げる可能性があります。
欠陥報告
以下の動作変更欠陥報告は以前に発行された C++ 標準に遡って適用されました。
| DR | 適用先 | 発行時の動作 | 正しい動作 |
|---|---|---|---|
| LWG 2901 | C++17 | allocator-aware constructors provided but variant can't properly support allocators
|
constructors removed |
| P0739R0 | C++17 | converting constructor template interacts poorly with class template argument deduction | constraint added |
| LWG 3024 | C++17 | copy constructor doesn't participate in overload resolution if any member type is not copyable | defined as deleted instead |
| P0602R4 | C++17 | copy/move constructors may not be trivial even if underlying constructors are trivial | required to propagate triviality |
| P0608R3 | C++17 | converting constructor blindly assembles an overload set, leading to unintended conversions | narrowing and boolean conversions not considered |
例
| This section is incomplete Reason: no example |