Boost.Variant 为我们提供了一个定义在 中的类: boost::variant
。 既然 boost::variant
是一个模板, 你必须要指定至少一个参数。 Variant 所存储的数据类型就由这些参数来指定。 上面的例子就给 v 指定了 double
类型和 char
类型。 注意, 一旦你将一个 int
值赋给了 v, 你的代码将不会编译通过。
当然, 上面的例子也可以用一个 union
类型来实现, 但是与 union 不同的是: boost::variant
可以储存像 std::string
这样的 class 类型的数据。
- #include <boost/variant.hpp>
- #include <string>
- int main()
- {
- boost::variant<double, char, std::string> v;
- v = 3.14;
- v = 'A';
- v = "Hello, world!";
- }
要访问 v 中的数据, 你可以使用独立的 boost::get()
函数。
所有 类型的值都可以被直接写入标准输入流这样的流中, 这可以在一定程度上让你避开运行时错误的风险。
- #include <boost/variant.hpp>
- #include <string>
- #include <iostream>
- int main()
- boost::variant<double, char, std::string> v;
- v = 3.14;
- std::cout << v << std::endl;
- v = 'A';
- std::cout << v << std::endl;
- v = "Hello, world!";
- std::cout << v << std::endl;
- }
想要分别处理各种不同类型的数据, Boost.Variant 为我们提供了一个名为 boost::apply_visitor()
的函数。
boost::applyvisitor()
第一个参数需要传入一个继承自 boost::static_visitor
类型的对象。 这个类必须要重载 operator()()
运算符来处理 boost::variant
每个可能的类型。 相应的, 例子中的 _v 就重载了三次 operator() 来处理三种可能的类型: double
, char
和 std::string
。
的第二个参数是一个 boost::variant
类型的值。
在使用时, boost::apply_visitor()
会自动调用跟第二个参数匹配的 operator()()
。 示例程序中的 boost::apply_visitor()
就自动调用了三个不同的 operator 第一个是 double
类型的, 第二个是 char
最后一个是 std::string
。
boost::apply_visitor()
的优点不只是“自动调用匹配的函数”这一点。 更有用的是, boost::apply_visitor()
会确认是否 boost::variant
中的每个可能值都定义了相应的函数。 如果你忘记重载了任何一个函数, 代码都不会编译通过。
- #include <boost/variant.hpp>
- #include <boost/any.hpp>
- #include <vector>
- #include <string>
- #include <iostream>
- std::vector<boost::any> vector;
- public boost::static_visitor<>
- {
- template <typename T>
- void operator()(T &t) const
- {
- vector.push_back(t);
- }
- };
- 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 = "Hello, world!";
- boost::apply_visitor(output(), v);
既然 可以在编译期确定代码的正确性, 你就该更多的使用它而不是 boost::get()
。