14.3. Boost.Any
像 C++ 这样的强类型语言要求给每个变量一个确定的类型。 而以 JavaScript 为代表的弱类型语言却不这样做, 弱类型的每个变量都可以存储数组、 布尔值、 或者是字符串。
库 Boost.Any 给我们提供了 boost::any
类, 让我们可以在 C++ 中像 JavaScript 一样的使用弱类型的变量。
- #include <boost/any.hpp>
- int main()
- {
- boost::any a = 1;
- a = 3.14;
- a = true;
- }
为了使用 boost::any
, 你必须要包含头文件: boost/any.hpp
。 接下来, 你就可以定义和使用 boost::any
的对象了。
需要注明的是: boost::any
并不能真的存储任意类型的值; Boost.Any 需要一些特定的前提条件才能工作。 任何想要存储在 boost::any
中的值,都必须是可拷贝构造的。 因此,想要在 boost::any
存储一个字符串类型的值, 就必须要用到 std::string
, 就像在下面那个例子中做的一样。
- #include <boost/any.hpp>
- #include <string>
- int main()
- {
- boost::any a = 1;
- a = 3.14;
- a = true;
- a = std::string("Hello, world!");
- }
如果你企图把字符串 "Hello, world!" 直接赋给 a , 你的编译器就会报错, 因为由基类型 char
构成的字符串在 C++ 中并不是可拷贝构造的。
想要访问 boost::any
中具体的内容, 你必须要使用转型操作: boost::any_cast
。
- #include <boost/any.hpp>
- #include <iostream>
- int main()
- {
- boost::any a = 1;
- std::cout << boost::any_cast<int>(a) << std::endl;
- a = 3.14;
- std::cout << boost::any_cast<double>(a) << std::endl;
- a = true;
- std::cout << boost::any_cast<bool>(a) << std::endl;
- }
通过由模板参数传入 boost::any_cast
的值, 变量会被转化成相应的类型。 一旦你指定了一种非法的类型, 该操作会抛出 boost::bad_any_cast
类型的异常。
- #include <boost/any.hpp>
- #include <iostream>
- int main()
- {
- try
- {
- boost::any a = 1;
- std::cout << boost::any_cast<float>(a) << std::endl;
- }
- catch (boost::bad_any_cast &e)
- {
- std::cerr << e.what() << std::endl;
- }
- }
上面的例子就抛出了一个异常, 因为 float
并不能匹配原本存储在 a 中的 int
类型。 记住, 在任何情况下都保证 boost::any
中的类型匹配是很重要的。 在没有通过模板参数指定 short
或 long
类型时, 同样会有异常抛出。
既然 boost::bad_any_cast
继承自 std::bad_cast
, catch
当然也可以捕获相应类型的异常。
想要检查 boost::any
是否为空, 你可以使用 empty()
函数。 想要确定其中具体的类型信息, 你可以使用 type()
函数。
- #include <boost/any.hpp>
- #include <typeinfo>
- #include <iostream>
- int main()
- {
- boost::any a = 1;
- if (!a.empty())
- {
- const std::type_info &ti = a.type();
- std::cout << ti.name() << std::endl;
- }
- }
上面的例子同时用到了 empty()
和 type()
函数。 empty()
将会返回一个布尔值, 而 type()
则会返回一个在 typeinfo
中定义的 std::type_info
值。
作为对这一节的总结, 最后一个例子会向你展示怎样用 boost::any_cast
来定义一个指向 boost::any
中内容的指针。
- #include <boost/any.hpp>
- #include <iostream>
- int main()
- {
- boost::any a = 1;
- int *i = boost::any_cast<int>(&a);
- std::cout << *i << std::endl;
- }
你需要做的就是传递一个 boost::any
类型的指针, 作为 boost::any_cast
的参数; 模板参数却没有任何改动。