Namespaces
Variants

std:: variant

From cppreference.net
Utilities library
ヘッダーで定義 <variant>
template < class ... Types >
class variant ;
(C++17以降)

クラステンプレート std::variant は型安全な union を表現します。

variant のインスタンスは、任意の時点でその代替型のいずれかの値を保持するか、エラーの場合には値を保持しません(この状態は達成が困難です。 valueless_by_exception を参照してください)。

unionと同様に、variantが何らかのオブジェクト型 T の値を保持する場合、 T オブジェクトは variantオブジェクト内にネストされます

variantは参照、配列、または型 void を保持することが許可されていません。

variantは同じ型を複数回保持すること、および同じ型の異なるcv修飾バージョンを保持することが許可されています。

共用体の 集約初期化 時の動作と一貫して、デフォルト構築されたvariantはその最初の代替型の値を保持します。ただし、その代替型がデフォルト構築可能でない場合は除きます(その場合、variantもデフォルト構築可能ではありません)。ヘルパークラス std::monostate を使用することで、そのようなvariantをデフォルト構築可能にすることができます。

テンプレート引数なしで std::variant の定義をインスタンス化するプログラムはill-formedです。 std :: variant < std:: monostate > を代わりに使用できます。

プログラムが explicit または partial 特殊化の std::variant を宣言する場合、そのプログラムは診断不要のill-formedとなる。

目次

テンプレートパラメータ

Types - このvariantに格納される可能性のある型。すべての型は Destructible 要件を満たさなければならない(特に、配列型と非オブジェクト型は許可されない)。

メンバー関数

variant オブジェクトを構築する
(public member function)
variant とその保持する値を破棄する
(public member function)
variant を代入する
(public member function)
オブザーバー
variant が保持する代替型のゼロベースのインデックスを返す
(public member function)
variant が無効な状態かどうかをチェックする
(public member function)
モディファイア
variant 内に値をその場で構築する
(public member function)
他の variant と交換する
(public member function)
ビジテーション
(C++26)
variant が保持する引数で提供されたファンクタを呼び出す
(public member function)

非メンバー関数

(C++17)
1つ以上の variant が保持する引数で提供されたファンクタを呼び出す
(関数テンプレート)
variant が現在指定された型を保持しているかどうかをチェックする
(関数テンプレート)
インデックスまたは型(型が一意の場合)を指定してvariantの値を読み取り、エラー時には例外をスローする
(関数テンプレート)
(C++17)
インデックスまたは型(一意の場合)を指定して、指し示される variant の値へのポインタを取得し、エラー時にはnullを返す
(関数テンプレート)
(C++17) (C++17) (C++17) (C++17) (C++17) (C++17) (C++20)
variant オブジェクトをその含まれる値として比較する
(関数テンプレート)
std::swap アルゴリズムを特殊化する
(関数テンプレート)

ヘルパークラス

(C++17)
デフォルト構築可能でない型の variant の最初の代替型として使用するためのプレースホルダ型
(クラス)
variant の値への不正なアクセス時にスローされる例外
(クラス)
コンパイル時に variant の代替型リストのサイズを取得する
(クラステンプレート) (変数テンプレート)
コンパイル時にインデックスで指定された代替型の型を取得する
(クラステンプレート) (エイリアステンプレート)
std::variant のハッシュサポート
(クラステンプレート特殊化)

ヘルパーオブジェクト

無効状態の variant のインデックス
(定数)

注記

機能テスト マクロ 標準 機能
__cpp_lib_variant 201606L (C++17) std::variant : 型安全な共用体
202102L (C++23)
(DR17)
std::visit std::variant から派生したクラス用
202106L (C++23)
(DR20)
完全な constexpr std::variant
202306L (C++26) メンバー関数 visit

#include <cassert>
#include <iostream>
#include <string>
#include <variant>
int main()
{
    std::variant<int, float> v, w;
    v = 42; // vはintを含む
    int i = std::get<int>(v);
    assert(42 == i); // 成功
    w = std::get<int>(v);
    w = std::get<0>(v); // 前の行と同じ効果
    w = v; // 前の行と同じ効果
//  std::get<double>(v); // エラー: [int, float]にdoubleは存在しない
//  std::get<3>(v);      // エラー: 有効なインデックス値は0と1
    try
    {
        std::get<float>(w); // wはfloatではなくintを含む: 例外をスローする
    }
    catch (const std::bad_variant_access& ex)
    {
        std::cout << ex.what() << '\n';
    }
    using namespace std::literals;
    std::variant<std::string> x("abc");
    // 変換コンストラクタは曖昧でない場合に機能する
    x = "def"; // 変換代入も曖昧でない場合に機能する
    std::variant<std::string, void const*> y("abc");
    // char const*が渡されるとvoid const*にキャストされる
    assert(std::holds_alternative<void const*>(y)); // 成功
    y = "xyz"s;
    assert(std::holds_alternative<std::string>(y)); // 成功
}

出力例:

std::get: wrong index for variant

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
LWG 2901 C++17 std::uses_allocator の特殊化が提供されていたが、
variant はアロケータを適切にサポートできない
特殊化を削除
LWG 3990 C++17 プログラムが std::variant の明示的特殊化または
部分特殊化を宣言可能であった
この場合、プログラムは不適格
(診断は要求されない)
LWG 4141 C++17 ストレージ割り当ての要件が
紛らわしかった
含まれるオブジェクトは
variant オブジェクト内に
ネストされなければならない

関連項目

インプレース構築タグ
(タグ)
(C++17)
オブジェクトを保持する場合と保持しない場合があるラッパー
(クラステンプレート)
(C++17)
任意の CopyConstructible 型のインスタンスを保持するオブジェクト
(クラス)