std::variant
是 C++17 引入的一种类型安全的联合体,用来存储多个可能类型中的一种值,且保证使用时的类型安全。相比于传统的 union
,std::variant
不仅能够存储不同类型的值,还能自动管理复杂类型的构造与析构。接下来,介绍如何快速上手 std::variant
。
1. 定义 std::variant
使用 std::variant
可以定义一个变量,该变量可以持有多种不同类型的值,但一次只能存储一种。
#include <iostream>
#include <variant>
int main() {
std::variant<int, float, std::string> v; // v 可以是 int、float 或 std::string
// 设置为 int 类型
v = 42;
std::cout << std::get<int>(v) << std::endl;
// 设置为 float 类型
v = 3.14f;
std::cout << std::get<float>(v) << std::endl;
// 设置为 std::string 类型
v = "Hello, std::variant!";
std::cout << std::get<std::string>(v) << std::endl;
return 0;
}
2. 访问 std::variant
的值
std::variant
的值可以通过 std::get<type>
或 std::get<index>
访问。
std::variant<int, float, std::string> v = 42;
// 使用类型访问
std::cout << std::get<int>(v) << std::endl;
// 使用索引访问,0 表示第一个类型
std::cout << std::get<0>(v) << std::endl;
注意:
- 如果你尝试访问的类型与当前存储的类型不匹配,程序会抛出
std::bad_variant_access
异常。
std::variant<int, float, std::string> v = 42;
try {
std::cout << std::get<float>(v); // 当前不是 float 类型,会抛出异常
} catch (const std::bad_variant_access& e) {
std::cout << "Wrong type access: " << e.what() << std::endl;
}
3. 检查当前类型
你可以使用 std::holds_alternative<T>(variant)
来判断 std::variant
当前是否持有某种类型。
if (std::holds_alternative<int>(v)) {
std::cout << "v holds an int" << std::endl;
}
4. 访问当前存储类型的索引
你可以使用 v.index()
获取当前存储值的类型在 std::variant
中的索引。
std::cout << "Index: " << v.index() << std::endl; // 0 表示 int,1 表示 float,依次类推
5. 使用 std::visit
访问 std::variant
std::visit
是 std::variant
的一个访问工具,它使用一个可调用对象(如 lambda 表达式或函数)来访问 std::variant
的值,而无需手动判断当前的类型。
#include <iostream>
#include <variant>
#include <string>
int main() {
std::variant<int, float, std::string> v = "Hello";
std::visit([](auto&& arg) {
std::cout << arg << std::endl; // 打印不同类型的值
}, v);
return 0;
}
6. 常见应用场景
- 存储多种类型的值:当需要一个变量存储多种可能的类型时,
std::variant
比union
更灵活和安全。 - 事件系统:可以使用
std::variant
来构建一种通用的事件系统,不同事件类型对应不同的variant
。 - 解析数据:如解析 JSON 或 XML 等格式化数据,数据字段可能是不同的类型。
小结
std::variant
可以存储多个类型之一,并且类型安全。- 通过
std::get<type>
或std::get<index>
访问值。 - 使用
std::holds_alternative
判断存储类型,使用std::visit
处理不同类型的值。