Boost::any可以存取任意类型,是用模板实现的,不过它设计得非常巧妙,其本身不是个模板,而是用一个模板类的成员来进行数据存储的,这使得我们可以写出这样的代码:
boost::any x((std::string(“Hello Cruel World!”));
x = 123;
x = 3.1416f;
….
但是如何把数据转变回来呢?
Boost::any提供了几个非成员模板函数any_cast,都需要RTTI支持
还有两个不安全的cast
template<typenameValueType>
inline ValueType * unsafe_any_cast(any * operand)
{
return &static_cast<any::holder<ValueType>*>(operand->content)->held;
}
template<typenameValueType>
inline const ValueType * unsafe_any_cast(const any * operand)
{
return unsafe_any_cast<ValueType>(const_cast<any *>(operand));
}
不许要RTTI支持(注释中说unsafe_any_cast随时都有可能被移除)。
所以,boost::any转换前必须知道它存的是什么类型才能正确还原数据,这是一个不足。比如
boost::any x(std::string(“Hello Cruel World!”));
std::string hello = any_cast<std::string>(x);
很容易发现还有一个不足之处就是你每次cast的时候都要写很长的一串any_cast<ValueTyp>,与其构造函数简洁的写法相比实在不和谐,用过的人一定深有体会。所以我想说的补充就是简化类型转化的写法。其实我们可以再加个操作符用户自定义类型转换函数来达到这个目的
在public成员函数那块加入
template<typenameValueType> operator ValueType()
{
return *unsafe_any_cast<ValueType>(this);
}
template<typenameValueType> operator ValueType() const
{
return *unsafe_any_cast<ValueType>(this);
}
于是乎
std::string hello = any_cast<std::string>(x);
可以简写成
std::string hello = x;
还有很多,比如
any a;
a = 163;
int i = a;
a = 2.7182818;
double e = a;
a = 3.1415926f;
float pi = any(3.1416f);
a = string("hello any");
string s = a;
cout<< i <<"\ne="<< e << "\npi="<< pi << "\n" << s << endl;
是不是方便了许多?
附上我提取的any.hpp,加入了文中的补充内容,可以直接用这一个头文件
话说怎么传附件?