std::variant是C++17引入的类型安全联合体,可存储多种类型之一并运行时明确当前类型;它通过内部索引和类型标签确保访问安全,支持std::get、std::holds_alternative和std::visit等操作。
std::variant 是 C++17 引入的类型安全联合体(type-safe union),它能在一个对象中存储多种不同类型中的某一种,同时在运行时明确知道当前存的是哪一种——彻底避免了传统 union 的类型擦除和未定义行为风险。
传统 union 不记录当前活跃成员,读写错误类型会触发未定义行为;std::variant 内部自带“当前索引”(index)和类型标签,所有访问都受检查:
std::get(v) 或 std::get(v) 访问前会做运行时校验(debug 模式下抛 std::bad_variant_access)std::holds_alternative(v) 判断是否持有某类型std::visit 对不同情况统一处理,无需手动 switch index假设你想表示一个可能为整数、浮点数或字符串的值:
#include#include #include using MyVariant = std::variant
; MyVariant v1 = 42; // 自动推导为 int MyVariant v2 = 3.14; // 推导为 double MyVariant v3 = std::string{"hi"}; // 必须显式构造 string,否则会被当 const char*
访问方式有三种常用形式:
std::get(v1) —— 按类型取,失败抛异常std::get(v1) —— 按序号取(0=first type=int),同样带检查std::holds_alternative(v1) —— 先判断再取,避免异常比起一堆 if (holds_alternative<...>),std::visit 更简洁、更不易漏分支:
std::visit([](const auto& x) {
us
ing T = std::decay_t;
if constexpr (std::is_same_v) {
std::cout << "int: " << x << '\n';
} else if constexpr (std::is_same_v) {
std::cout << "double: " << x << '\n';
} else if constexpr (std::is_same_v) {
std::cout << "string: " << x << '\n';
}
}, v1); 也可以用重载的 lambda(C++17 起支持):
auto printer = [](const auto& x) {
std::cout << x << '\n';
};
std::visit(printer, v1); // 自动匹配对应类型的 operator()std::monostate 可作为占位类型,让 variant 支持“空状态”,比如 std::variant<:monostate int std::string>
std::variant> ),但可通过 std::unique_ptr 间接实现递归结构std::any 更轻量