C++17にはstd::variantというライブラリが追加されます。 variantは組み込みのunionよりリッチなインターフェイスを持った型安全なunionです。*1 Visual Studio 2017にも入りましたので簡単なサンプルを書いてみました
#include <variant> #include <iostream> #include <string> struct visitor { void operator()(int) const { std::cout << "it's int" << std::endl; } void operator()(std::string const&) const { std::cout << "it's string" << std::endl; } }; int main() { std::variant<int, std::string> const vars[] = {3, "hello"}; for (auto const& it : vars) { // visitでvariantの値にアクセスできる。値をファンクタに渡すことが出来ない場合はコンパイルエラーになる // (必要ならば)ファンクタはジェネリクスにするかオーバーロードしておく std::visit(visitor{}, it); // holds_alternativeはvariantにholds_alternativeのテンプレート引数に渡した型の値を持っていればtrueを返す // variantのテンプレート引数に存在しない型を指定するとコンパイルエラーになる std::cout << std::boolalpha << std::holds_alternative<int>(it) << std::endl; // std::getでvariantが保持している値の参照を取得する // テンプレート引数に渡した型の値を保持していない場合はstd::bad_variant_accessを投げる try { int value = std::get<int>(it); std::cout << "holding int value: " << value << std::endl; } catch (std::bad_variant_access const& e) { std::cout << e.what() << std::endl; } // std::get_ifでvariantが保持している値のポインタを取得する // テンプレート引数に渡した方のあたいを保持していない場合はnullptrを返す if (auto const value = std::get_if<int>(&it)) { std::cout << "holding int value: " << *value << std::endl; } else { std::cout << "not found" << std::endl; } } }
実行結果
it's int true holding int value: 3 holding int value: 3 it's string false bad variant access not found Press any key to continue . . .
*1:代数データ型素人なので違っていたら優しく指摘してください…