Boost::any实现分析
在看《Conversations》的时候,看到有一章,专门讲到了Boost::any,不禁又勾起我对Boost的敬佩之情。
打开any.hpp,看到any类的实现非常简单,2个构造函数,1个拷贝构造函数,2个赋值运算符重载,1 个指针类型的成员变量,以及几个辅助函数。可正是这样一个简单的类,实现了极为巧妙极其方便的功能。看看C++对COM中的Variant的封装,把各种 想得到的数据类型都嵌入到union中,同时需要一个附加字段来指定当前实际的数据类型,代码看起来不但臃肿冗余,而且也不好用。
来看看any的实现代码,首先它是被放在boost名字空间的,其次,any当然不是一个模板类,不然在对不同的数据类型实例化后,不能方便地以统一的类型表示了:
class any
{
public: // structors
any()
: content(0)
{
}
template<typename ValueType>
any(const ValueType & value)
: content(new holder<ValueType>(value))
{
}
any(const any & other)
: content(other.content ? other.content->clone() : 0)
{
}
~any()
{
delete content;
}
// ……………………
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private: // representation
template<typename ValueType>
friend ValueType * any_cast(any *);
template<typename ValueType>
friend ValueType * unsafe_any_cast(any *);
#else
public: // representation (public so any_cast can be non-friend)
#endif
placeholder * content;
};
这是它的构造函数、拷贝构造函数和析构函数,content是一个placeholder的指针。从使用的角度看,any在实例化时,可以用任何类型 的数据来初始化,除了用any以外,其它的数据类型时,都会调用那个模板构造函数,它将生成一个holder对象,把初始数据存放在该对象中,同时把该 holder对象的指针存放在成员变量content中。由此可知,holder类肯定是从placeholder类继承而来的,之后的代码中就可以见证 到这一点。Boost根据编译器是否支持成员模板友员,特地小心地处理了any_cast和unsafe_any_cast两个辅助函数。
class placeholder
{
public: // structors
virtual ~placeholder()
{
}
public: // queries
virtual const std::type_info & type() const = 0;
virtual placeholder * clone() const = 0;
};
template<typename ValueType>
class holder : public placeholder
{
public: // structors
holder(const ValueType & value)
: held(value)
{
}
public: // queries
virtual const std::type_info & type() const
{
return typeid(ValueType);
}
virtual placeholder * clone() const
{
return new holder(held);
}
public: // representation
ValueType held;
};
再看placeholder和holder类的实现,原来placeholder只是个接口声明,holder才是个模板类,可以根据不同的数据类型实例化,这样无论实例化后的类型是什么,在any中都可以用placeholder的指针来表示了。
Any的实现虽然很简单,但对于C++模板新手的我来说,还是很值得学习的!