QVariant,std::variant,std::any,std::optional,std::visit,union
一、Qt中的QVariant
QVariant和std::any有些类似,std::variant更像是std::any的一个子集
二、C++标准库中的std::variant(C++17)
QVariant和std::variant序列化与反序列化。(序列化就是把程序数据转换为可以传输或者写入文件的数据)
std::variant模板参数列表中如果包含没有默认构造函数的类型,可以使用std::monostate消除错误,例如std::variant<std::monostate, NoDefConstr> myVar
std::variant可以继承,例如class sub: public std::variant<int, float>
std::variant抛出异常类型为std::bad_variant_access
std::visit是用来操作std::variant的转载:C++17之std::visit
点击查看代码
#include <variant>
#include <string>
#include <vector>
int main()
{
std::variant<int, int, int, float, float, std::string> var1;
//var1 = 2.0f; //错误,variant模板初始化有多个float,不知道是给第几个float赋值
std::variant<int, int, float, float, char, char> var11{ std::in_place_index<3>,2 }; // 初始化为第三个类型
var1.emplace<1>(2.0f); //正确,指定具体第几个类型,会强制类型转换
auto index1 = var1.index(); // 1
var1.emplace<5>("test"); //正确
//var1.emplace<2>("test"); //错误
//var1.emplace<int>(2); //错误
std::variant<int, float,char> var2;
var2.emplace<int>(2); // 没有多个int类型时才可以这样赋值
var2 = 2.0f;
var2 = 3.0f; // 覆盖前面的值
var2 = 'x'; // 覆盖前面的值
auto index2 = var2.index(); // 此时var2的值为'x',是var2的第2个类型(从0开始)
//auto ret1 = std::get<1>(var2); //抛出异常,因为var2的值为'x'是第2个类型
//auto ret2 = std::get<int>(var2); //抛出异常,var2值的类型为char
auto ret1 = std::get<2>(var2); // ret1 = 'x'
auto ret2 = std::get<char>(var2); // ret2 = 'x'
// 注意get_if的参数必须为指针
auto ret3 = std::get_if<int>(&var2); // 获取失败返回nullptr
auto ret4 = std::get_if<char>(&var2); // 获取成功返回char*
std::vector<std::variant<int,float,char>> vec;
vec.emplace_back(2);
vec.emplace_back(2.0f);
vec.emplace_back('x');
//vec.emplace_back("xxx"); //错误,因为variant中没有"xxx"的类型
int test = 0;
return 0;
}
三、C++标准库中的std::any(C++17)
简单地说,std::variant 只能存放指定类型(模板初始化列表中的类型)的对象,而 std::any 可以存放任意(合法的)类型的对象。
四、C++标准库中的std::optional(C++17)
点击查看代码
#include <iostream>
#include <optional>
#include <string>
// convert string to int if possible:
std::optional<int> asInt(const std::string& s)
{
try
{
return std::stoi(s);
}
catch (...)
{
return std::nullopt;
}
}
int main()
{
for (auto s : { "42", " 077", "hello", "0x33" })
{
// convert s to int and use the result if possible:
std::optional<int> oi = asInt(s);
if (oi) {
std::cout << "convert '" << s << "' to int: " << *oi << "\n";
}
else {
std::cout << "can't convert '" << s << "' to int\n";
}
}
}
std::pair<T,bool>
和std::option
的联系
五、 union
union和std::variant有些类似,在C++程序中一般很少用到