C++17で導入されたstd::variantは、
複数の型のうちどれか1つを安全に保持できる型安全な共用体です。
本記事では、std::variantの基本的な使い方を紹介したいと思います。
前提知識
-
C++の基礎構文を理解している
std::variantとは
std::variantは、C++17 で導入された 複数の型のうちどれか1つを保持できる型安全な共用体です。
従来のunionと違い、std::variantは現在どの型が入っているかを自動で管理し、非トリビアル型(std::string など、メモリをそのままコピーするとダメな型)も安全に扱えます。
サンプルコード
main.cpp
//-----------------------------------------------------------------
//! @file main.cpp
//! @brief std::variantの使い方サンプル
//! @author つきの
//-----------------------------------------------------------------
#include <iostream>
#include <variant>
#include <string>
//-----------------------------------------------------------------
//! @class A
//! @brief Draw() メソッドを持つクラス A
//-----------------------------------------------------------------
struct A {
//-----------------------------------------------------------------
//! @brief Draw() メソッド
//-----------------------------------------------------------------
void Draw() const {
std::cout << "A::Draw()" << std::endl;
}
};
//-----------------------------------------------------------------
//! @class B
//! @brief Draw() メソッドを持つクラス B
//-----------------------------------------------------------------
struct B {
//-----------------------------------------------------------------
//! @brief Draw() メソッド
//-----------------------------------------------------------------
void Draw() const {
std::cout << "B::Draw()" << std::endl;
}
};
// エントリポイント
int main() {
// A または B のどちらかを保持できる variant
std::variant<A, B> v;
v = A{}; // A を入れる
// 現在入っている型に応じて Draw() を呼び分ける
std::visit([](auto& x) {
x.Draw();
}, v);
v = B{}; // B を入れる
std::visit([](auto& x) {
x.Draw();
}, v);
return 0;
}
宣言
宣言時は、テンプレートに保持したい型を記述します。
main.cpp
// A または B のどちらかを保持できる variant
std::variant<A, B> v;
代入
入れたい型を代入するだけで代入可能です。
代入するだけで自動で型が入れ替わります。
main.cpp
v = A{}; // A を入れる
メンバ関数を使用したい場合
std::visitを使用することで、メンバ関数を使用することが出来ます。
main
// 現在入っている型に応じて Draw() を呼び分ける
std::visit([](auto& x) {
x.Draw();
}, v);
総括
-
std::variantを使用することで、複数の型の中から一つの値をを同じ変数で保持することが出来る -
メンバ関数を使用したい場合は
std::visitを使用する