std::variant代表了类型安全的union类型,与union类似,std::variant的一个实例要么存储了可选类型中的一个值,要么没有存储。但与union比,其优势是可以判断当前真实的存储类型并且可以存储结构体这种复杂的数据结构。下面直接给一个实例:
#include <variant>
#include <string>
#include<cassert>
#include<iostream>
int main() {
// 定义两个variant类型实例
std::variant<int, float> v, w;
v = 18;
// index 可以判断实际对应的类型,,默认第一种类型。
std::cout << "Corresponding type is " << w.index() << std::endl;
int i = std::get<int>(v);
std::cout << "value is " << i << std::endl;
w = std::get<int>(v);
w = std::get<0>(v); // 与上一行功能相同
w = v; // 与上一行功能相同
// 类型对不上会抛出异常
try {
std::get<float>(w);
}
catch (const std::bad_variant_access& ex) {
std::cout << ex.what() << std::endl;
}
// 避免使用 try catch,可以使用get_if
float* fres = std::get_if<float>(&v);
if (fres) {
std::cout << "float value is " << *fres << std::endl;
}
else {
std::cout << "does not contain a value" << std::endl;
}
v = 1.23f;
fres = std::get_if<float>(&v);
if (fres) {
std::cout << "float value is " << *fres << std::endl;
}
else {
std::cout << "does not contain a value" << std::endl;
}
// index 可以判断实际对应的类型
std::cout << "Corresponding type is " << w.index() << std::endl;
// holds_alternative 判断当前是否使用此类型
if (std::holds_alternative<float>(v)) {
std::cout << "now using float type" << std::endl;
}
else {
std::cout << "not using float type" << std::endl;
}
return 0;
}
执行结果如下:
Corresponding type is 0
value is 18
bad variant access
does not contain a value
float value is 1.23
Corresponding type is 0
now using float type
可以看到查用的函数,get可以获取指定类型的数据,如果当前存储的不是此类型则会抛异常,为了解决此问题可以catch此异常,或者使用get_if通过判断指针是否为空来获取,holds_alternative可以用来判断当前是否存储的是该类型数据。