C++的std::visit如何使用(C++,开发技术)

时间:2024-05-04 05:14:56 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

1. 使用对象函数方式访问

例1:

#include<iostream>#include<variant>#include<string>structMyVisitor{voidoperator()(doubled)const{std::cout<<d<<'\n';}voidoperator()(inti)const{std::cout<<i<<'\n';}voidoperator()(conststd::string&s)const{std::cout<<s<<'\n';}};intmain(){std::variant<int,double,std::string>var1(42),var2(3.14),var3("visit");std::visit(MyVisitor(),var1);//callsoperator()formatchinginttypestd::visit(MyVisitor(),var2);//callsoperator()formatchingdoubletypestd::visit(MyVisitor(),var3);//callsoperator()formatchingstd::stringtypereturn0;}

结果如下:

C++的std::visit如何使用

如果操作符()不支持所有可能的类型,或者调用不明确,则visit()调用是编译时错误。还可以使用访问者修改当前类型的值(但不能分配新类型的值)。

例2:

#include<iostream>#include<variant>#include<string>structTwice{voidoperator()(double&d)const{d*=2;}voidoperator()(int&i)const{i*=2;}voidoperator()(std::string&s)const{s=s+s;}};intmain(){std::variant<int,double,std::string>var1(42),var2(3.14),var3("visit");std::visit(Twice(),var1);//callsoperator()formatchinginttypestd::visit(Twice(),var2);//callsoperator()formatchingdoubletypestd::visit(Twice(),var3);//callsoperator()formatchingstd::stringtypestd::cout<<std::get<int>(var1)<<std::endl;std::cout<<std::get<double>(var2)<<std::endl;std::cout<<std::get<std::string>(var3)<<std::endl;return0;}

结果如下:

C++的std::visit如何使用

注意,对象操作符应该为const函数,因为它们是无状态的(它们不改变它们的行为,只改变传递的值,即不改变成员变量的值)。

2. 使用泛型Lambdas访问

使用这个特性最简单的方法是使用泛型lambda,它是一个函数对象,用于任意类型:

例3:

#include<iostream>#include<variant>#include<string>autoprintvariant=[](constauto&val){std::cout<<val<<std::endl;};intmain(){std::variant<int,double,std::string>var1(42),var2(3.14),var3("visit");std::visit(printvariant,var1);std::visit(printvariant,var2);std::visit(printvariant,var3);return0;}

结果如下:

C++的std::visit如何使用

这里,泛型lambda定义了一个闭包类型,其中函数调用操作符作为成员模板:

classCompilerSpecifyClosureTypeName{public:template<typenameT>autooperator()(constT&val)const{std::cout<<val<<'\n';}};

也可以使用lambda来修改当前选项的值:

例4:

#include<iostream>#include<variant>#include<string>autoprintvariant=[](constauto&val){std::cout<<val<<std::endl;};intmain(){std::variant<int,double,std::string>var1(42),var2(3.14),var3("visit");std::visit([](auto&val){val=val+val;},var1);std::visit([](auto&val){val=val+val;},var2);std::visit([](auto&val){val=val+val;},var3);std::visit(printvariant,var1);std::visit(printvariant,var2);std::visit(printvariant,var3);return0;}

结果如下:

C++的std::visit如何使用

甚至可以使用编译时if语言特性以不同的方式处理不同的备选值:

例5:

#include<iostream>#include<variant>#include<string>autodblvar=[](auto&val){ifconstexpr(std::is_convertible_v<decltype(val),std::string>){val=val+"test";}else{val+=2;}};intmain(){std::variant<int,double,std::string>var1(42),var2(3.14),var3("visit");std::visit(dblvar,var1);std::visit(dblvar,var2);std::visit(dblvar,var3);std::cout<<std::get<int>(var1)<<std::endl;std::cout<<std::get<double>(var2)<<std::endl;std::cout<<std::get<std::string>(var3)<<std::endl;return0;}

这里,对于一个std::string类型备选项,泛型lambda的调用实例化它的泛型函数调用模板来计算:

val = val + “ test”;

而对于其他类型备选项,如int或double, lambda的调用实例化其通用函数调用模板来计算:

val += 2;

结果如下:

C++的std::visit如何使用

3. 使用重载的Lambdas来访问

通过为函数对象和lambdas使用一个重载器,还可以定义一组lambdas,其中使用最佳匹配作为访问者。假设,重载器定义为重载,如下所示:

template<typename...Ts>structoverload:Ts...{usingTs::operator()...;};//basetypesarededucedfrompassedarguments:template<typename...Ts>overload(Ts...)->overload<Ts...>;

可以使用重载访问一个变量,为每个选项提供lambdas:

std::variant<int,std::string>var(42);...std::visit(overload{//callsbestmatchinglambdaforcurrentalternative[](inti){std::cout<<"int:"<<i<<'\n';},[](conststd::string&s){std::cout<<"string:"<<s<<'\n';},},var);

还可以使用泛型lambda。总是用最好的搭配。例如,要修改variant对象的当前类型备选项的值,可以使用重载将字符串和其他类型的值“加倍”:

autotwice=overload{[](std::string&s){s+=s;},[](auto&i){i*=2;},};

使用此重载,对于字符串类型备选项,将添加当前值,而对于所有其他类型,将值乘以2,这演示了variant对象的以下应用程序:

std::variant<int,std::string>var(42);std::visit(twice,var);//value42becomes84...var="hi";std::visit(twice,var);//value"hi"becomes"hihi"

例 6:

#include<iostream>#include<variant>#include<string>template<typename...Ts>structoverload:Ts...{usingTs::operator()...;};template<typename...Ts>overload(Ts...)->overload<Ts...>;autotwice=overload{[](std::string&s){s+=s;},[](auto&i){i*=2;},};intmain(){std::variant<int,std::string>var1(42),var3("visit");std::visit(twice,var1);std::visit(twice,var3);std::visit(overload{//callsbestmatchinglambdaforcurrentalternative[](inti){std::cout<<"int:"<<i<<'\n';},[](conststd::string&s){std::cout<<"string:"<<s<<'\n';},},var1);std::visit(overload{//callsbestmatchinglambdaforcurrentalternative[](inti){std::cout<<"int:"<<i<<'\n';},[](conststd::string&s){std::cout<<"string:"<<s<<'\n';},},var3);return0;}

结果如下:

C++的std::visit如何使用

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:C++的std::visit如何使用的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:怎么用python制作简单计算器功能下一篇:

5 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18