新西兰服务器

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


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

发布时间:2022-02-07 11:05:38 来源:高防服务器网 阅读:57 作者:iii 栏目:开发技术

这篇文章主要介绍“C++的std::visit如何使用”,在日常操作中,相信很多人在C++的std::visit如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++的std::visit如何使用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

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::variant<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() (const 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 constexpr (std::is_convertible_v<decltype(val), std::string>)      {          val = val + " test";      }      else      {          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()...;  };  // base types are deduced from passed 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);

还可以使用泛型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++的std::visit如何使用”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注高防服务器网网站,小编会继续努力为大家带来更多实用的文章!

[微信提示:高防服务器能助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

[图文来源于网络,不代表本站立场,如有侵权,请联系高防服务器网删除]
[