Any库概述
Any库可以改进程序:
#对任意的类型提供类型安全(typesafe)的存储和安全的检索;
#提供了在标准库容器中存放异构类型(heterogeneous type)的方法
#传递类型所通过的层无须了解任何该类型的信息.
Any库提供一个类型:any,它允许对任意的类型进行存储,以便稍后进行检索,而且还不损失类型的安全性.很多情况下,我们可能希望在同一个容器中存储互不相关的类型.还有很多情况下,某些特定的代码仅仅关心从一个点到另一个点传递数据的方式,而不关心数据的类型.表面上看,这些事情很容易做.它们可以通过一个诸如void *的无差别类型来实现.同样,它们还可以通过使用一个有差别的联合(discriminated union)来实现.另外,有许多变体类型都通过一些类型标记机制来实现的.然而,所有这些实现方式都缺乏类型安全性,而且只有在最可控的情形下才有可能故意绕过类型系统.标准库的容器对它们所包含的类型进行参数化,因此对这些容器中存储异构类型的元素提出了一个看上去似乎不可能实现的挑战.幸运的是,解决方案不一定必须使用void *,因为Any库允许存储不同类型的对象用于后续的检索.但是还是无法在不了解实际的情况下检索所存储的值,类型安全从而得到保证.
Any库的一个重要特性就是它提供了在标准容器中存储异构类型对象的能力.另外,它还是一种变体数据类型(variant data type).而这正是C++标准库非常需要但又缺乏的数据类型.
Any类
类any 允许对任意的类型进行类型安全的存储和检索.与无差别的类型不同,any类保存了类型的信息,而且实际上还不不允许在不知道正确类型的情况下获取所存储的值.当然,若要查询类型的信息和测试所保存的值的可选项,办法还是有的.但是最终,调用者还是必须知道any对象中所存储的值的确切类型,否则any类就拒绝访问,对any类来说,可以把它看作是一个上了锁的保险箱,没有匹配的钥匙,就不能进入其中.any类对它所存储的类型有以下要求:
#可复制构造(copyConstructible):它必须可以复制这个类型.
#析构函数不抛出异常:就象所有的析构函数所应该的那样的.
#可赋值(Assignable):为了保证异常安全(不符合可赋值要求的类型也可以用于any类,但没有强异常安全的保证).
下面是any类的公共接口:
Namespace boost
{
Class any {
Public:
Any();
Any(const any &);
Template<typename ValueType> any (const ValueType&);
~any();
Any & swap(any &);
Any & operator=(const any &);
Template<type ValueType&> any & operator=(const ValueType&);
Bool empty() const;
Const std::type_info & type() const;
};
}
Any();该默认构造函数创建一个any类的空实例,即一个不含有值的any类.当然,也就无法从一个空的any类中检索值,因为它里面没有值存在.
Any(const any & other);该构造函数创建一个已有的any对象的独特副本.其中other中所包含的值被复制并存储到this中.
Template<typename ValueType> any (const ValueType&);这个模板化的构造函数存储传递构造函数的类型为ValueType的参数的一份副本.其中参数是一个const引用,因此传递一个临时对象以存储到any中是合法的.注意,该构造函数不是显式的,那么any就回难以使用,而且还会影响额外的安全性.
~any();该析构函数销毁any类所包含的值,但要注意,因为裸指针(raw pointer)的析构并不会对指针调用运算符delete或运算delete[],所以在any中使用指针时,应该把裸指针包装在一个诸如shared_ptr的智能指针中.
Any &swap(any & other);
交换两个any对象中所存储的值.
Any & operator = (const any & other);若any实例是非空的,那么该函数会丢弃所存储的值,然后存入other值的一份副本.
Template<type ValueType&> any & operator=(const ValueType&);若any的实例是非空的,那么该函数会丢弃所存储的值,然后存入value的一份副本,其中value可以是符合any要求的任意类型.
Bool empty() const;该函数指示当前是否包含值,但不用考虑值的类型.因此,当any中存放指针时,即使该指针为空,empty函数也要返回flase.
Const std::type_info & type() const;该函数指示any对象中所存储值的类型.若any对象为空,则该该函数返回的类型为void.
Any类中的自由函数
Template <typename ValueType> ValueType any_cast(const any& operand);
Any_cast函数允许访问any中所存储的值.其参数为要检索其中的值的any对象.如果类型ValueType与所存储的类型不符,则抛出一个类型为bad_any_cast的异常.这里需要注意的是,该函数的语法和dynamic_cast函数的语法相似.
Template <typename ValueType > const ValueType* any_cast(const any *operand);
Any_cast函数的重载,其参数为 any对象的指针,它返回的是一个指向所存储值的指针.若any对象中的类型不是ValueType,那么该重载将返回一个空指针.注意,该重载函数的语法仍然和dynamic_cast函数的语法相似.
Template <typename ValueType > ValueType* any_cast(any *operand);
Any_cast函数的另一个重载,它与前一个重载版本相似,但前一个版本的参数类型和返回类型都使用了const限定的指针,而这个重载版本则不是这样的.
异常
Bad_any_cast
当试图将any对象转换为该对象所存储类型以外的其他类型时,将抛出该异常.bad_any_cast异常派生自std::bad_cast.需要注意,当使用指针参数调用any_cast函数时,不会抛出异常(类似于使用指针型调用dynamic_cast函数返回空指针);但是,当使用引用类型调用any_cast函数时,则在失败时抛出异常.
使用用法
Any库定义在命令空间boost中.我们可以用类any来存储值,随后用模板函数any_cast来检索所存储的值.为了使用any类,程序中需要包含头文件”boost/any.cpp”.创建一个可以存储任意类型的值的实例非常简单,如下所示:
Boost::any a;
对上述实例赋予某个类型的值也很容易,如下:
A = std::string(“A string”);
A = 42;
A = 3.1415;
Any类几乎可以接受任何类型的值.但是,为了真正能使用存储在any中的值,需要检索它.为此,需要知道这个值的类型.
Std::string s = boost::any_cast<std::string> (a);
//throws boost::bad_any_cast
上述代码不能得到正确结果,这是因为对象a中当前所包含的值是double类型的,这时any_cast将抛出一个类型为bad_any_cast的异常.但下面的代码可得到正确的结果.
Double d = boost::any_cast<double>(a);
Any类只有在知道类型的前提下才可以访问它的值.一般要牢记:类any用于存储值.而模板函数any_cast用于检索存储值.
现有三个类A,B,C,它们没有共同的基类,想要把它们存储到一个std::vector中.(any提供了一种更好的解决方法,但是它还没有解决对类型的依赖.)
#include <iostream>
#include <string>
#include <utility>
#include <vector>
#include “boost/any.hpp”
Class A {
Public:
Void some_function() {std::cout<<”A::somefunction()/n”;}
}
Class B {
Public:
Void some_function() {std::cout<<”B::somefunction()/n”;}
}
Class C {
Public:
Void some_function() {std::cout<<”C::somefunction()/n”;}
}
Int main()
{
Std::cout<<”Example of using any./n”;
Std::vector<boost::any> store_anything;
Store_anything.push_back(A());
Store_anything.push_back(B());
Store_anything.push_back(C());
Store_anything.push_back(std::string(“This is fantastic!”));
Store_anything.push_back(3);
Store_anything.push_back(std::make_apir(true,7.92));
Void print_any(boost::any & a);
//defined later; reports on the value in a
Std::for_each(store_anything.begin(),store_anything.end(),print_any());
}
Void print_any(boost::any & a)
{
If(A *pA = boost::any_cast<A>(&a))
{
pA->some_function();
}
Else if ((B*pB= boost::any_cast<B>(&a))
{
pB->some_function();
}
Else if ((C*pC= boost::any_cast<C>(&a))
{
pC->some_function();
}
Else
{
Try{
Std::cout<<boost::any_cast<std::string>(a)<<endl;
}
Catch(boost::bad_any_cast&){
Std::cout<<”error!/n”;
}
}
}

375

被折叠的 条评论
为什么被折叠?



