C++にはint
やdouble
といったC言語と共通の組み込み型(基本型)に加えてSTLの提供する型を使用できます。ここではSTLの提供する型のうち複数の型の値や無効値を一つの型としてまとめて扱う型variant
、any
、optional
を紹介します。
概要
クラス | ヘッダー | 概要 | cpprefjpへのリンク |
---|---|---|---|
variant |
<variant> |
テンプレート引数で与えた型のいずれかの値を保持する型。空状態も指定可能。 | リンク |
any |
<any> |
どんな型の値でも保持できる型。 | リンク |
optional |
<optional> |
元の型の値か統一的な無効値(nullopt )を保持する型。 |
リンク |
variant
variant
は扱う型を明示的に複数指定できます。std::string
やstd::wstring
を指定した場合は文字列("..."
、L"..."
等)を代入してstd::wstring
型の値を設定できます。ただし、any
は代入と取得(any_cast
)が同じ型を要求することから厳格さはany
が勝ります。
以下はint
、double
、std::wstring
を保持できるstd::variant
型でint
とstd::wstring
を管理する例です。
#include <iostream> #include <string> #include <variant> int main() { std::variant<int, double, std::wstring> x(L"abcde"); std::wcout << std::get<std::wstring>(x) << std::endl; // std::wcout << std::get<int>(x) << std::endl; // std::bad_variant_access x = 1234; // std::wcout << std::get<std::wstring>(x) << std::endl; // std::bad_variant_access std::wcout << std::get<int>(x) << std::endl; return 0; }
テンプレート引数の最初にstd::monostate
を指定することで空状態も表現できます。variant
の初期値は最初のテンプレート引数の型のデフォルトコンストラクタから作成される ので、std::monospace
は最初のテンプレート引数に指定する必要があります。
#include <iostream> #include <string> #include <variant> int main() { std::variant<std::monostate, int, double, std::wstring> x; std::wcout << std::boolalpha << std::holds_alternative<std::monostate>(x) << std::endl; // true x = L"abcde"; std::wcout << std::boolalpha << std::holds_alternative<std::monostate>(x) << std::endl; // false return 0; }
any
any
は任意の型の値を保持できますが、保持する値の型と取得する型は同じ必要があります。したがって、Unicode文字列リテラルのconst wchar_t*
型を代入したany
型変数からstd::wstring
は取得できず、整数リテラル1
のint
型を代入したany
型変数からshort
型は取得できません。異なる型の取得は例外を発生します。
#include <any> #include <iostream> #include <string> int main() { std::any x(L"abcde"); std::wcout << std::any_cast<const wchar_t*>(x) << std::endl; // std::wcout << std::any_cast<std::wstring>(x) << std::endl; // std::bad_any_cast(同じ型ではないため) // std::wcout << std::any_cast<int>(x) << std::endl; // std::bad_any_cast // std::wcout << std::any_cast<short>(x) << std::endl; // std::bad_any_cast x = 1234; // std::wcout << std::any_cast<const wchar_t*>(x) << std::endl; // std::bad_any_cast // std::wcout << std::any_cast<std::wstring>(x) << std::endl; // std::bad_any_cast std::wcout << std::any_cast<int>(x) << std::endl; std::wcout << std::any_cast<short>(x) << std::endl; // std::bad_any_cast(同じ型ではないため) return 0; }
optional
optional
は特定の型の値を保持するか無効状態を表せる型です。無効値を保持する場合、値の取得(value()
)は例外を発生します。
以下はoptional
でint
型の値か無効状態を保持する例です。
#include <iostream> #include <string> #include <optional> int main() { std::wcout.setf(std::wcout.boolalpha); auto x = std::make_optional(123); std::wcout << x.value() << std::endl; // 123 std::wcout << x.has_value() << std::endl; // true std::wcout << (bool)x << std::endl; // true x.reset(); // std::wcout << x.value() << std::endl; // std::bad_optional_access std::wcout << x.has_value() << std::endl; // false std::wcout << (bool)x << std::endl; // false return 0; }
補足
これらの型の他、STLはメモリ管理、文字列、イテレーター、ビュー等多数の型を公開しています。また、Boostの導入でより多くの機能を使用できます。