在 C++17 标准以后,std::variant 提供了一种轻量级的、类型安全的多态容器。它可以在运行时存放若干种不同类型的值,并且编译器会在编译期帮助你检查类型。相比传统的基类指针和 void*,std::variant 更安全、可读性更高。本文将从基本用法、访问方式、访问者模式、以及常见问题四个部分,系统介绍如何使用 std::variant 构建一个类型安全的多态容器。
1. 基本声明与初始化
#include <variant>
#include <string>
#include <iostream>
using MyVariant = std::variant<int, double, std::string>;
上述定义创建了一个名为 MyVariant 的别名,它可以保存 int、double 或 std::string 三种类型中的任意一种。下面展示几种不同的初始化方式:
MyVariant v1 = 42; // int
MyVariant v2 = 3.14; // double
MyVariant v3 = std::string("hello"); // std::string
若想显式指定所需的类型索引,可以使用 std::variant 的构造函数:
MyVariant v4( std::in_place_index <2>, "world" ); // 位置索引为 2,对应 std::string
2. 访问与查询
2.1 std::get 与 std::get_if
最直接的访问方式是 std::get,它要求你确定当前存放的是哪种类型,否则会抛出 std::bad_variant_access。
int i = std::get <int>(v1); // 成功
// int j = std::get <double>(v1); // 运行时异常
如果不确定类型,可以使用 std::get_if,它返回一个指针,若类型不匹配则返回 nullptr:
if (auto p = std::get_if<std::string>(&v3)) {
std::cout << "string: " << *p << '\n';
}
2.2 index 与 holds_alternative
v.index() 返回当前类型在类型列表中的索引(从 0 开始)。
`std::holds_alternative