绪章 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=(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
, 这个函数会进行类型检查。
 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值