版权所有 © 2002, 2003 Eric Friedman, Itay Maman
版权所有 © 2014-2025 Antony Polukhin
根据 Boost 软件许可协议 1.0 版发布。(请参阅随附文件 LICENSE_1_0.txt
或在 https://boost.ac.cn/LICENSE_1_0.txt 复制副本)
目录
variant
类模板是一个安全、通用的、基于堆栈的可区分联合容器,为以统一的方式操作来自异构类型集合的对象提供了简单的解决方案。标准容器(如 std::vector
)可以被认为是“多值,单类型”,而 variant
则是“多类型,单值”。
boost::variant
的显著特点包括
boost::apply_visitor
进行编译时类型安全的值访问。boost::get
进行运行时检查的显式值检索。boost::make_recursive_variant
和 boost::recursive_wrapper
支持递归 variant 类型。很多时候,在 C++ 程序开发过程中,程序员发现自己需要以统一的方式操作几种不同的类型。实际上,C++ 通过其 union
关键字直接为这些类型提供了语言支持
union { int i; double d; } u; u.d = 3.14; u.i = 3; // overwrites u.d (OK: u.d is a POD type)
然而,C++ 的 union
构造在面向对象的环境中几乎毫无用处。该构造进入该语言主要是为了保持与 C 的兼容性,C 仅支持 POD(普通旧数据)类型,因此不接受表现出非平凡构造或析构的类型
union { int i; std::string s; // illegal: std::string is not a POD type! } u;
显然,需要另一种方法。典型的解决方案是动态分配对象,然后通过公共基类型(通常是虚基类 [Hen01] 或更危险的 void*
)来操作这些对象。然后可以通过多态向下转型构造(例如,dynamic_cast
,boost::any_cast
等)来检索具体类型的对象。
然而,由于以下原因,这种解决方案非常容易出错
此外,即使正确实现,这些解决方案也往往会由于堆的使用、虚函数调用和多态向下转型而导致相对显著的抽象惩罚。
boost::variant
类模板以安全、直接和高效的方式解决了这些问题。以下示例演示了如何使用该类
#include "boost/variant.hpp" #include <iostream> class my_visitor : publicboost::static_visitor
<int> { public: int operator()(int i) const { return i; } int operator()(conststd::string
& str) const { return str.length(); } }; int main() {boost::variant
< int, std::string > u("hello world"); std::cout << u; // output: hello world int result =boost::apply_visitor
( my_visitor(), u ); std::cout << result; // output: 11 (i.e., length of "hello world") }