类库大魔王
类库大魔王 多年C++、Go项目经验,长期从事跨平台(Windows/macOS/iOS/Android)应用架构设计与开发。

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++模板新手的我来说,还是很值得学习的!

感觉本文不错,不妨小额鼓励我一下!
如果你有Visa、MasterCard之类的国际银行卡,也可以考虑以下选项:
如果你看不到评论框,说明Disqus被墙了。