本人生性做事不认真, 又不善于总结,为一改前貌,决定每周写一点东西,以此督促自己改掉以前的臭毛病.
首先列出源代码,来给俯瞰全局
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;
}
public: // modifiers
any & swap(any & rhs)
{
std::swap(content, rhs.content);
return *this;
}
template<typename ValueType>
any & operator=(const ValueType & rhs)
{
any(rhs).swap(*this);
return *this;
}
any & operator=(const any & rhs)
{
any(rhs).swap(*this);
return *this;
}
public: // queries
bool empty() const
{
return !content;
}
const std::type_info & type() const
{
return content ? content->type() : typeid(void);
}
#ifndef
BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private: // types
#else
public: // types (public so any_cast can be non-friend)
#endif
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;
};
#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;
};
上面有一些有意思的地方,any其实没干啥事,事情都让
holder
干了,holder有个基类placeholder,这是一个抽象类,它在这里起着关键作用。holder是个模板类,不能在any中保存它的指针,那么就只能保存它基类的指针,在通过基类指针进行实际操作。
来看个例子在接着往下分析.
boost::any int_any(1);
看看这一句干了什么,首先当然是调用any的构造函数
template<typename ValueType>
any(const ValueType & value)
: content(new holder<ValueType>(value))
{
}
这里就做了一件事,初始化content,
placeholder * content;
可见content是一个placeholder的指针,当然这里初始化的时候实际上是用的一个holder
(new holder<ValueType>(value))
型的指针来初始化。在这里ValueType被解析成int类型。
接着再看holder的构造函数又做了什么。
holder(const ValueType & value)
: held(value)
{
}
它的作用就是初始化held,
ValueType held;
这里held 就是一个int型的值
boost::any int_any(1);
最终就是
holder(const int &value)
:held(1)
{
}
然后看看any支持的操作
any(const any & other)
: content(other.content ? other.content->clone() : 0)
首先看看拷贝构造函数,如果other.content不为NULL(any的默认构造函数是把content指针置为NULL),就调用other.content->clone(),此时实际调用的是
virtual placeholder * clone() const
{
return new holder(held);
}
相当于content = new holder(other.content.held);
然后看看
any & swap(any & rhs)
{
std::swap(content, rhs.content);
return *this;
}
Swap
函数,这个swap函数极其简单,单纯的调用std::swap完事
template<typename ValueType>
any & operator=(const ValueType & rhs)
{
any(rhs).swap(*this);
return *this;
}
看看赋值操作符,这是个有趣的应用,生成一个临时any在和它交换。
赋值操作符的另一个重载
any & operator=(const any & rhs)
{
any(rhs).swap(*this);
return *this;
}
也差不多,以下是两种赋值操作符的用法
boost::any int_any(1);
int_any = 1.0;
boost::any double_any(1.0);
int_any = double_any;
来看看这个函数
bool empty() const
{
return !content;
}
没得什么好讲得,单纯得返回content是否为NULL。
const std::type_info & type() const
{
return content ? content->type() : typeid(void);
}
这一个函数返回constent中得held到底是什么类型,它调用得是holder的
virtual const std::type_info & type() const
{
return typeid(ValueType);
}
函数,这个函数也非常简单。
最后不要担心内存泄漏之类的问题
~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
那就是BOOST_NO_MEMBER_TEMPLATE_FRIENDS这个宏,有的编译器是不支持友元模板的(如果你的编译器是这样的,最好换一个对模板支持更好的编译器)如果支持没什么好说的content;是私有的,并且申明两个友元函数。如果不支持,又要其他函数使用这个成员,无奈之下只能把它设为公有的,虽然这样不太符合面向对象的思想:)
对any的剖析就告一段落,下面来看和它息息相关的两个函数和一个类
class bad_any_cast : public std::bad_cast
{
public:
virtual const char * what() const throw()
{
return "boost::bad_any_cast: "
"failed conversion using boost::any_cast";
}
};
没有什么好说的,主要就是为了反应一会儿针对any的转型错误。
来看看这个转型函数
template<typename ValueType>
ValueType * any_cast(any * operand)
{
return operand && operand->type() == typeid(ValueType)
? &static_cast<any::holder<ValueType> *>(operand->content)->held
: 0;
}
主要工作就是取held的地址,然后返回一个ValueType的指针,当然前提是held要于ValueType的类型一致
template<typename ValueType>
const ValueType * any_cast(const any * operand)
{
return any_cast<ValueType>(const_cast<any *>(operand));
}
这个函数就没什么好说了。
template<typename ValueType>
ValueType any_cast(const any & operand)
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
#ifdef
BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// If 'nonref' is still reference type, it means the user has not
// specialized 'remove_reference'.
// Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
// to generate specialization of remove_reference for your class
// See type traits library documentation for details
BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
#endif
const nonref * result = any_cast<nonref>(&operand);
if(!result)
boost::throw_exception(bad_any_cast());
return *result;
}
再来看看这一个函数,不要看这么多东西,其实有用的没多少
BOOST_DEDUCED_TYPENAME
就是typename,应为remove_reference是一个模板,为了不把type从一类型
误解为一个成员,就要加上这个typename告诉编译器。当然针对某些编译器的出色能力,能够区分这两种情况,那么这个宏就什么都没有。可见作为一个类库的设计者真是费尽苦心。
remove_reference
的作用是如果是移出引用。
让后下面的工作就是交给上面的两个函数来做,当然要检查一些那个指针是不是为NULL。
template
<typename ValueType>
ValueType any_cast(any & operand)
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
#ifdef
BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// The comment in the above version of 'any_cast' explains when this
// assert is fired and what to do.
BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
#endif
nonref * result = any_cast<nonref>(&operand);
if(!result)
boost::throw_exception(bad_any_cast());
return *result;
}
这个函数就不用讲了,同上。
template<typename ValueType>
ValueType * unsafe_any_cast(any * operand)
{
return &static_cast<any::holder<ValueType> *>(operand->content)->held;
}
这是一个不安全转型的版本,主要就是它不进行类型检查。
template<typename ValueType>
const ValueType * unsafe_any_cast(const any * operand)
{
return any_cast<ValueType>(const_cast<any *>(operand));
}
这个函数有个令我困惑的地方。它是unsafe_any_cast版本,但为什么它的实现调用的是any_cast
,
这个函数会进行类型检查。