• 山寨STL实现之traits,construct&destruct


    traits技术被广泛应用于STL中,通过它您可以轻松的萃取出一个对象的特性。在STL中也是通过它来实现性能的最优化,比如一个对象是个POD对象(Plain Old Data),则在拷贝过程中直接可以通过memcpy等函数拷贝,而无需调用拷贝构造函数或operator=。

    先来看看STL中最基本的对象iterator

            template <typename T, typename Size = size_t, typename Difference = ptrdiff_t>
            struct iterator
            {
                typedef T                               value_type;
                typedef Difference                      difference_type;
                typedef T*                              pointer;
                typedef T&                              reference;
                typedef const T*                        const_pointer;
                typedef const T&                        const_reference;
                typedef iterator<T, Size, Difference>   self;
            };
    
            template <typename T, typename Size = size_t, typename Difference = ptrdiff_t>
            struct const_iterator : public iterator<T>
            {
            };

    由以上代码可知,对于每一个iterator必须定义其value_type,size_type,difference_type,pointer,reference,const_pointer,const_reference和self类型。 
    一、value_type
    value_type指示了该迭代器所保存的值类型
    二、difference_type
    difference_type用来指示两个迭代器之间的距离类型
    三、pointer,reference,const_pointer,const_reference
    分别是所指之物的指针,引用,指针常量和引用常量的类型
    四、self
    self为该迭代器自身的类型

    下面来看一下iterator_traits,iterator_traits主要用来萃取迭代器iterator的值类型等

            template <typename Iterator>
            struct iterator_traits
            {
                typedef typename Iterator::value_type      value_type;
                typedef typename Iterator::difference_type difference_type;
                typedef typename Iterator::pointer         pointer;
                typedef typename Iterator::reference       reference;
                typedef typename Iterator::const_pointer   const_pointer;
                typedef typename Iterator::const_reference const_reference;
                typedef typename Iterator::self            self_type;
            };

    这里有一点可以提前预告一下,vector作为一个容器,其内部是使用指针作为迭代器的,那么我们如何萃取出它的值类型等呢?
    答案很简单,特例化,那么我们就来为iterator_traits分别做两种T*和const T*的特例化

            template <typename T>
            struct iterator_traits<T*>
            {
                typedef T         value_type;
                typedef ptrdiff_t difference_type;
                typedef T*        pointer;
                typedef T&        reference;
                typedef const T*  const_pointer;
                typedef const T&  const_reference;
                typedef T*        self_type;
            };
    
            template <typename T>
            struct iterator_traits<const T*>
            {
                typedef T         value_type;
                typedef ptrdiff_t difference_type;
                typedef T*        pointer;
                typedef T&        reference;
                typedef const T*  const_pointer;
                typedef const T&  const_reference;
                typedef const T*  self_type;
            };

    至此,我们可以用iterator_traits萃取出每种iterator的值类型等内容了。

    之前已经说到了,通过traits可以萃取出一些对象的特性,从而提高代码的效率。事实确实如此,通过traits可萃取出一个对象是否是一个POD对象,对于一个POD对象,我们在拷贝时,不应该使用其拷贝构造函数或是operator=,而用memcpy则效率更高。
    下面我们来看一下__type_traits

            struct __true_type
            {
            };
    
            struct __false_type
            {
            };
    
            template <typename T>
            struct __type_traits
            {
                typedef __true_type  has_default_construct;
                typedef __true_type  has_copy_construct;
                typedef __true_type  has_assign_operator;
                typedef __true_type  has_destruct;
                typedef __false_type is_POD;
            };

    不得不提的是其中分别用__true_type和__false_type来表示是否存在这个特性。

    那么我们如何萃取出基础类型诸如int,char等的特性呢?
    答案依然是特例化,这里代码不再贴出,文末会给出完整代码的详细地址。

    最后我们使用一个hash_destruct的函数来获取出这个类型是否有析构函数。

            template <typename T>
            inline auto has_destruct(const T&)->decltype(static_cast<__type_traits<T>::has_destruct*>(0))
            {
                return static_cast<typename __type_traits<T>::has_destruct*>(0);
            }
    
            template <typename T>
            inline auto has_destruct(T*)->decltype(static_cast<__type_traits<T>::has_destruct*>(0))
            {
                static_assert(false, "Please use const T& not T*");
                return static_cast<typename __type_traits<T>::has_destruct*>(0);
            }
    
            template <typename T>
            inline auto has_destruct(const T*)->decltype(static_cast<__type_traits<T>::has_destruct*>(0))
            {
                static_assert(false, "Please use const T& not const T*");
                return static_cast<typename __type_traits<T>::has_destruct*>(0);
            }

    不得不提的是C++0x的确很强大,可以通过形参来确定返回值的类型,这样我们就可以萃取出这个类型的has_destruct域是__true_type或是__false_type了。

    最后来看看construct和destruct的代码,在STL中对象的内存分配和构造是被分开的,对于基础对象int,char等,在析构时我们无需调用其析构函数。
    下面来看construct和destruct的实现

            template <typename T1, typename T2>
            inline void construct(T1* p, const T2& value)
            {
                new (p) T1(value);
            }
    
            template <typename T>
            inline void destruct(T* p, __true_type*)
            {
                p->~T();
            }
    
            template <typename T>
            inline void destruct(T*, __false_type*)
            {
            }
    
            template <typename ForwardIterator>
            inline void destruct(ForwardIterator first, ForwardIterator last)
            {
                while(first != last)
                {
                    destruct(&*first, has_destruct(*first));
                    ++first;
                }
            }

    至此,关于traits技术和construct及destruct的讲解已完成,完整的代码请到http://qlanguage.codeplex.com/下载

  • 相关阅读:
    NHibernate开源框架Cuyahoga学习之数据访问实现
    Petshop4.0 缓存设计学习
    Jquery实现ToolTip之元素定位
    客户单操作Cookie
    .Net 通过MySQLDriverCS操作MySQL
    NHibernate的基本使用
    提高ASP.NET性能的十大方法
    工作流引擎下基于表达式Tree复杂验证的实现
    C#注册表操作
    WinForm应用程序中的ComboBox实现ReadOnly功能
  • 原文地址:https://www.cnblogs.com/lwch/p/2592640.html
Copyright © 2020-2023  润新知