首页 > 作文

C++17之std::visit的具体使用

更新时间:2023-04-04 22:19:01 阅读: 评论:0

目录
1. 使用对象函数方式访问2. 使用泛型lambdas访问3. 使用重载的lambdas来访问

它们必须明确地为每种可能的类型提供函数调用操作符。然后,使用相应的重载来处理当前的备选项类型。

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

例1:

#include <iostream>#include <variant>#include <string> struct myvisitor{    void operator()(double d) const {        std::cout << d << '\n';    }    void operator()(int i) const {        std::cout << i << '\n';    }    void operator()(const std::string& s) const {        std::cout << s << '\n';}};int main(){    std::variant<int, double, std::string> var1(42), var2(3.14), var3("visit");     std::visit(myvisitor(), var1); // calls operator() for matching int type     std::visit(myvisitor(), var2); // calls operator() for matching double type     std::visit(myvisitor(), var3); // calls operator() for matching std::string type     return 0;}

结果如下:

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

例2:

#include <iostream>#include <variant>#include <string> struct twice{    void operator()(double& d) const {        d *= 2;    }    void operator()(int& i) const {        i *= 2;    }    void operator()(std::string& s) const {        s = s + s;    }}; int main(){    std::v成人高考英语试题ariant<int, double, std::string> var1(42), var2(3.14), var3("visit");     std::visit(twice(), var1); // calls operator() for matching int type     std::visit(twice(), var2); // calls operator() for matching double type     std::visit(twice(), var3); // calls operator() for matching std::string type     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;     return 0;}

结果如下:

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

2. 使用泛型lambdas访问

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

例3:

#include <iostream>#include <variant>#include <string> auto printvariant = [](const auto& val) {    std::cout << val << std::endl;}; int main(){    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);     return 0;}

结果如下:

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

class compilerspecifyclosuretypename {public:template<typename t>auto operator() (con一节课多少分钟st t& val) const {    std::cout << val << '\n';}};

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

例4:

#include <iostream>#include <variant>#include <string> auto printvariant = [](const auto& val){    std::cout << val << std::endl;}; int main(){    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);     return 0;}

结果如下:

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

例5:

#include <iostream>#include <variant>#include <string> auto dblvar = [](auto& val){    if con饮用水水源地stexpr (std::is_convertible_v<decltype(val), std::string>)    {        val = val + " test";    }    el    {        val += 2;    }}; int main(){    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;     return 0;}

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

val = val + “ test”;

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

val += 2;

结果如下:

3. 使用重载的lambdas来访问

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

template<typename... ts>struct overload : ts...{using ts::operator()...;};// ba types are deduced from pasd arguments:template<typename... ts>overload(ts...) -> overload<ts...>;

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

std::variant<int, std::string> var(42);...std::visit(overload{ // calls best matching lambda for current alternative[](int i) { std::cout << "int: " << i << '\n'; },[](const std::string& s) {std::cout << "string: " << s << '\n'; },},var);

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

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

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

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

例 6:

#include <iostream>#include <variant>#include <string> template<typename... ts>struct overload : ts...{    using ts::operator()...;}; template<typename... ts>overload(ts...)->overload<ts...>; auto twice = overload{        [](std::string& s) { s += s; },        [](auto& i) { i *= 2; },}; int main(){    std::variant<int, std::string> var1(42) , var3("visit");     std::visit(twice, var1);    std::visit(twice, var3);        std::visit(overload{ // calls best matching lambda for current alternative        [](int i) { std::cout << "int: " << i << '\n'; },        [](const std::string& s) {        std::cout << "string: " << s << '\n'; },        },        var1);        std::visit(overload{ // calls best matching 同底数幂相除lambda for current alternative       [](int i) { std::cout << "int: " << i << '\n'; },       [](const std::string& s) {       std::cout << "string: " << s << '\n'; },        },        var3);        return 0;}

结果如下:

到此这篇关于c++17之std::visit的具体使用的文章就介绍到这了,更多相关c++17 std::visit内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-04 22:18:59,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/b0ed2f276720365ef62fea958b9f1f7a.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:C++17之std::visit的具体使用.doc

本文 PDF 下载地址:C++17之std::visit的具体使用.pdf

标签:类型   函数   对象   可以使用
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图