boost::any实现分析
来源:互联网 发布:java 类对象降序 编辑:程序博客网 时间:2024/06/07 16:17
这里提到的boost::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; } 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=(any rhs) { 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; private: // intentionally left unimplemented holder & operator=(const holder &); };#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类没有用模版参数,这是为什么呢?显而易见,因为any的设计初衷我想就是提供如下的使用方式:
boost::any any_value(10);boost::any any_value1("123");
而非
boost::any<int> any_value(10);boost::any<std::string> any_value1("123");
即,提供一种动态的数据类型,并接受单个对象的同时能够获得它的类型
如果用了模版参数变成boost::any<int> any_value(10)这样,那any_value就确定是int类型,并且在使用时还需要传类型作为模版参数。所以,any必须不能是模板类。那么问题来了,如果any不是模板类,它怎么才能泛化的保存各种类型呢?答案就在虚基类placeholder和它的派生模板类holder。
因为any不是模板类不能保存泛型数据,那就需要将原数据用一种容器包起来,然后让any持有一个指针,指向这个容器。那么很明显,这个容器类必须是模板类,因为这样它才能保存泛型数据,而又因为any不是模板类,它的任何数据成员都不能是泛型的,那就需要一个基类,让any持有这个基类的指针,而“容器”从这个基类派生并带模版参数。这样就解决了问题,即让原来需要泛型化存储数据的的any不泛型化,转而定义一种泛型化容器来保存数据,而any自己握住该泛型化容器基类的指针指向这个泛型化的容器。太绕了...绕这么一圈的目的,就是为了开始提到的涉及初衷:提供一种动态的数据类型,并接受单个对象的同时能够获得它的类型。
核心的分析完了,再分析些具体的。
既然需要
boost::any any_value(10);boost::any any_value1 = "str";
那就需要对any的带参构造函数、拷贝构造函数处理成带模版参数的,并重载=操作符(也带模版参数)。这里可以仔细看看重载=操作符里的swap函数,很多重载=操作符的都是采用swap的方式实现赋值的。
template<typename ValueType> any & operator=(const ValueType & rhs) { any(rhs).swap(*this); return *this; }这里先创建一个临时对象any(rhs),再调用swap进行底层数据交换,注意与*this交换数据的是临时对象,所以rhs的底层数据并未更改,在swap结束后临时对象拿住了*this的底层数据,而这时*this也拿到了临时对象构造时创建的rhs的数据副本。临时对象由于函数结束生命周期也结束而析构掉,则原来*this的底层数据也就没了。这样就实现了将*this原来的底层数据干掉,让*this持有rhs的底层数据的副本。
再说下从any对象中获取数据的方式
int a = 0;boost::any any_value(a);int b = any_value;//这是不允许的int b = any_cast<int>(any_value);//正确
直接将any对象赋给某种类型的对象是不允许的,编不过,因为any对象并没有重载目标对象的操作符(也不可能重载,那么多类型)。因此就需要采用any_cast的方式,当然,还有一个unsafe_any_cast的函数,差别就是any_cast在转换时会进行类型匹配检查,只有类型一致的,才会转,否则抛出异常,而unsafe_any_cast不进行类型匹配检查而直接转。
代码如下:
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"; } }; template<typename ValueType> ValueType * any_cast(any * operand) { return operand && #ifdef BOOST_AUX_ANY_TYPE_ID_NAME std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0#else operand->type() == typeid(ValueType)#endif ? &static_cast<any::holder<ValueType> *>(operand->content)->held : 0; } template<typename ValueType> inline const ValueType * any_cast(const any * operand) { return any_cast<ValueType>(const_cast<any *>(operand)); } template<typename ValueType> ValueType any_cast(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 nonref * result = any_cast<nonref>(&operand); if(!result) boost::throw_exception(bad_any_cast()); return *result; } template<typename ValueType> inline ValueType any_cast(const 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 return any_cast<const nonref &>(const_cast<any &>(operand)); } // Note: The "unsafe" versions of any_cast are not part of the // public interface and may be removed at any time. They are // required where we know what type is stored in the any and can't // use typeid() comparison, e.g., when our types may travel across // different shared libraries. template<typename ValueType> inline ValueType * unsafe_any_cast(any * operand) { return &static_cast<any::holder<ValueType> *>(operand->content)->held; } template<typename ValueType> inline const ValueType * unsafe_any_cast(const any * operand) { return unsafe_any_cast<ValueType>(const_cast<any *>(operand)); }
- boost::any实现分析
- Boost::any分析
- Boost::any分析
- Boost::any分析
- Boost::any分析
- boost any 实现技法
- boost::any实现
- boost::any类型实现原理
- boost.any实现任意类型存储
- boost::any
- Boost::any
- BOOST--any
- boost::any
- boost::any
- Boost::Any
- boost::any
- boost any
- boost any
- C# Dictionary的用法 KeyValuePair<TKey, TValue> 结构
- 黑马程序员_java字符串
- C++知识点复习
- Struts2如何调用Action的方法
- 事件循环与线程 二
- boost::any实现分析
- gcc 关于math.h编译链接
- Android Connectivity分析(1)- ConnectivityManager
- linux中开机启动时,根据不同的登录ip来决定执行不同的操作
- 程序员应该了解的 10 个面向对象设计原则
- install nose in the ENV which had installed python3.3
- 黑马程序员_JDBC
- LM2576S上电瞬间烧坏
- 热爱生命 - 汪国真