C++ Boost Variant示例超详细讲解

 更新时间:2022年11月09日 09:01:02   作者:无水先生  
Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称

一、提要

        Boost.Variant 提供了一个类似于 union 的名为 boost::variant 的类。您可以将不同类型的值存储在 boost::variant 变量中。在任何时候只能存储一个值。分配新值时,旧值将被覆盖。但是,新值的类型可能与旧值不同。唯一的要求是这些类型必须作为模板参数传递给 boost::variant,这样它们才能为 boost::variant 变量所知。

        boost::variant 支持任何类型。例如,可以将 std::string 存储在 boost::variant 变量中——这在 C++11 之前使用联合是不可能的。在 C++11 中,对联合的要求被放宽了。现在联合可以包含一个 std::string。因为 std::string 必须使用placement new 进行初始化,并且必须通过显式调用析构函数来销毁,所以使用 boost::variant 仍然有意义,即使在 C++11 开发环境中也是如此。

二、示例

        示例 24.1。使用 boost::variant

#include <boost/variant.hpp>
#include <string>
int main()
{
  boost::variant<double, char, std::string> v;
  v = 3.14;
  v = 'A';
  v = "Boost";
}

        boost::variant 在 boost/variant.hpp 中定义。因为 boost::variant 是一个模板,所以必须至少指定一个参数。一个或多个模板参数指定支持的类​​型。在示例 24.1 中,v 可以存储类型为 double、char 或 std::string 的值。但是,如果您尝试将 int 类型的值分配给 v,则生成的代码将无法编译。

        示例 24.2。使用 boost::get() 访问 boost::variant 中的值

#include <boost/variant.hpp>
#include <string>
#include <iostream>
int main()
{
  boost::variant<double, char, std::string> v;
  v = 3.14;
  std::cout << boost::get<double>(v) << '\n';
  v = 'A';
  std::cout << boost::get<char>(v) << '\n';
  v = "Boost";
  std::cout << boost::get<std::string>(v) << '\n';
}

        要显示 v 的存储值,请使用独立函数 boost::get()(参见示例 24.2)。

        boost::get() 期望对应变量的有效类型之一作为模板参数。指定无效类型将导致运行时错误,因为类型验证不会在编译时进行。

        boost::variant 类型的变量可以写入标准输出流等流,从而绕过运行时错误的风险(参见示例 24.3)。

        示例 24.3。在流上直接输出 boost::variant

#include <boost/variant.hpp>
#include <string>
#include <iostream>
int main()
{
  boost::variant<double, char, std::string> v;
  v = 3.14;
  std::cout << v << '\n';
  v = 'A';
  std::cout << v << '\n';
  v = "Boost";
  std::cout << v << '\n';
}

        对于类型安全的访问,Boost.Variant 提供了一个名为 boost::apply_visitor() 的函数。

        示例 24.4。使用访问者来提升::variant

#include <boost/variant.hpp>
#include <string>
#include <iostream>
struct output : public boost::static_visitor<>
{
  void operator()(double d) const { std::cout << d << '\n'; }
  void operator()(char c) const { std::cout << c << '\n'; }
  void operator()(std::string s) const { std::cout << s << '\n'; }
};
int main()
{
  boost::variant<double, char, std::string> v;
  v = 3.14;
  boost::apply_visitor(output{}, v);
  v = 'A';
  boost::apply_visitor(output{}, v);
  v = "Boost";
  boost::apply_visitor(output{}, v);
}

        作为其第一个参数,boost::apply_visitor() 期望从 boost::static_visitor 派生的类的对象。此类必须为它所作用的 boost::variant 变量使用的每种类型重载 operator()。因此,在示例 24.4 中,运算符重载了 3 次,因为 v 支持 double、char 和 std::string 类型。

        boost::static_visitor 是一个模板。 operator() 的返回值类型必须指定为模板参数。如果运算符没有返回值,则不需要模板参数,如示例中所示。

        传递给 boost::apply_visitor() 的第二个参数是一个 boost::variant 变量。

        boost::apply_visitor() 自动为第一个参数调用 operator() ,该参数与当前存储在第二个参数中的值的类型相匹配。这意味着每次调用 boost::apply_visitor() 时,示例程序都会使用不同的重载运算符——首先是用于 double 的运算符,然后是用于 char 的运算符,最后是用于 std::string 的运算符。

        boost::apply_visitor() 的优点不仅在于自动调用正确的运算符。此外,boost::apply_visitor() 确保为 boost::variant 变量支持的每种类型都提供了重载运算符。如果未定义三个重载运算符之一,则无法编译代码。

        如果重载的运算符在功能上是等效的,则可以使用模板简化代码(参见示例 24.5)。

        示例 24.5。使用带有 boost::variant 函数模板的访问者

#include <boost/variant.hpp>
#include <string>
#include <iostream>
struct output : public boost::static_visitor<>
{
  template <typename T>
  void operator()(T t) const { std::cout << t << '\n'; }
};
int main()
{
  boost::variant<double, char, std::string> v;
  v = 3.14;
  boost::apply_visitor(output{}, v);
  v = 'A';
  boost::apply_visitor(output{}, v);
  v = "Boost";
  boost::apply_visitor(output{}, v);
}

        因为 boost::apply_visitor() 确保了编译时代码的正确性,所以应该优先于 boost::get()。

到此这篇关于C++ Boost Variant示例超详细讲解的文章就介绍到这了,更多相关C++ Boost Variant内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一文带你掌握C++中的移动语义和完美转发

    一文带你掌握C++中的移动语义和完美转发

    这篇文章主要为大家详细介绍了C++中的移动语义和完美转发的相关知识,文中的示例代码讲解详细,对我们深入掌握C++有一定的帮助,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • C语言超详细讲解数据结构中双向带头循环链表

    C语言超详细讲解数据结构中双向带头循环链表

    带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单
    2022-04-04
  • 浅谈C++中replace()方法

    浅谈C++中replace()方法

    C++编程语言中的string应用方式多样化,每一种应用方式都能帮助我们提实现特定的功能需求。在这里我们将会为大家详细介绍一下其中一个比较重要的用法,有关C++ replace()函数的应用方式,需要的朋友可以参考下
    2015-11-11
  • C++使用TinyXML2实现解析和生成XML数据

    C++使用TinyXML2实现解析和生成XML数据

    TinyXML2是一个轻量级的、开源的C++库,专门用于解析和生成XML文档,本文主要为大家介绍了如何使用TinyXML2实现解析和生成XML数据,需要的可以参考下
    2024-04-04
  • C++中getline()和get()的方法浅析

    C++中getline()和get()的方法浅析

    大家都知道作为C++获取输入流的方法,几乎在任何一本资料书上getline()方法和get()方法都作为入门级的方法进行讲述,即便如此,笔者在学习C++的过程中仍经常忘记这二者的使用要点,可能也有C++的初学者对这两个方法还心存疑虑,本篇文章就这两个方法的使用进行简要阐述。
    2016-10-10
  • Qt5.9画五角星的方法

    Qt5.9画五角星的方法

    这篇文章主要为大家详细介绍了Qt5.9画五角星的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • C语言之system函数案例详解

    C语言之system函数案例详解

    这篇文章主要介绍了C语言之system函数案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++中求数组长度的方法详解

    C++中求数组长度的方法详解

    C++中没有直接提供求数组长度的方法,提供了sizeof(),begin(),end()等方法,可以供求数组长度使用,文中通过代码示例给大家讲解的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2023-12-12
  • C++实现哈希桶的详细教程

    C++实现哈希桶的详细教程

    这篇文章主要介绍了C++实现哈希桶的详细教程,哈希的底层是一个vector的数组,数组中的每个节点都有一个pair类型的数据,文中通过代码示例和图文讲解的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2024-06-06
  • VC++ 使用 _access函数判断文件或文件夹是否存在

    VC++ 使用 _access函数判断文件或文件夹是否存在

    这篇文章主要介绍了VC++ 使用 _access函数判断文件或文件夹是否存在的相关资料,需要的朋友可以参考下
    2015-10-10

最新评论