STL學習_萃取技術__type_traits

    之前在學習STL庫中的析構工具destory()時,提到過這樣一句話,此函數設法找到元素的數值型別,進而利用__type_traits<>求取適當措施。一直難以理解,現在自己總結了下自己對萃取技術的理解。

     讓自己困惑的程序:

    template<class T>

    void destroy(T *pointer)

    {

        pointer->~T();

    }

    template<calss ForwardIterator>

    void destroy(ForwardIterator first, ForwardIterator last)

    {

        __destroy(first, last, value_type(first));

    }

     template<class ForwardIterator, class T>

     void __destroy(ForwardIterator first, ForwardIterator last, T*)

     {

         typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;

         __destroy_aux(first, last, trivial_destructor());

     }

     //注意這裏判斷元素的數值型別是否有trivial destructor, 由於是__false_type,所以要對這個型別進行析構,所以

    //輪詢調用destroy()進行析構

    template<class ForwardIterator>

    void __destroy_aux(ForwardIterator first, ForwardIterator last, __false_type)

    {

         for( ; first < last; ++first){

            destroy(&*first);

        }

    }

    //由於是__true_type所以不用進行析構操作,系統會採用內存直接處理操作例如free

    template<class ForwardIterator>

    void __destroy_aux(ForwardIterator first, ForwardIterator last, __true_type)

    {

    }

    這裏有困惑,那麼看看萃取機制

    萃取技術,就是當函數,類這種一些封裝的通用算法中的某些部分會因爲數據類型不同而導致處理的邏輯不同,然而我們又不想因爲數據類型的差異而修改算法本身的封裝,所以採用萃取機制來解決這一問題。從而實現同一種操作因類型不同而異的效果。因此在STL中爲了提供通用的操作而又不想損失效率就採用traits編程技巧。


    __type_traits負責萃取型別特性,通常我們關注的型別特性有是否具備non-trivial defalt ctor?是否具備non-trivial copy ctor?是否具備non-trivial assignment operator?是否具備non-trivial dtor?如果答案是否定的(也就是說具備這些特性)就對這個型別進行構造,析構, 拷貝, 賦值等操作,這樣可以採用最有效率的措施。(比如一些自己定義的類,或者不是普通類型比如string類, 對象等,就要進行這樣的操作)如果答案是確定的(也就是說不具備這些特性,例如int, float. double, char等普通的類型就不具備這種特性)這些類型爲了提高效率直接採用內存處理操作,例如malloc() memcpy(),所以這種機制對於大規模操作頻繁的容器有着顯著的效率的提升。

    例如:我們準備對一個元素型別未知的數組進行拷貝操作,如果我們知道這個元素型別是否有一個trivial copy constructor,以便我們決定是否使用快速的memcpy(),還是使用慢速的拷貝構造函數。

    下面是SGI中<type_traits.h>中的__type_traits,提供的一種機制,允許針對不同型別屬性,在編譯期完成函數派送決定(意思是在編譯期就決定是採用快速的內存直接處理操作還是採用慢速的構造,析構,拷貝,賦值操作)

    struct __true_type{};

    struct __false_type{};

    template<calss type>

    struct __type_traits{

        typedef __true_type this_dummy_must_be_first;

        typedef __false_type has_trivial_default_constructor;

        typedef __false_type has_trivial_copy_constructor;

        typedef __false_type has_trivial_assignment_operator;

        typedef __false_type has_trivial_destructor;

        typedef __false_type is_POD_type;

    };

    SGI把所有的內嵌型別都定義爲__false_type,定義出最保守的值。但同時SGI還針對每一個型別設計了適當的__type_traits的特化版本

    例如:char類型,因爲對char類型進行初始化,刪除,賦值,複製,都可以通過快速的內存直接處理操作,所以這裏將__false_type改爲__true_type不具備這些特性。

    __STL_TEMPLATE_NULL struct __type_traits<char>{

        typedef __true_type has_trivial_default_constructor;

        typedef __true_type has_trivial_copy_constructor;

        typedef __true_type has_trivial_assignment_operator;

        typedef __true_type has_trivial_destructor;

        typedef __true_type is_POD_type;


    }

    瞭解這些,現在回頭看看最上面那個之前看不懂的destroy()析構工具,目的是將[first, last)範圍ie內的所有對象析構掉,我們不知道這個範圍有多大,如果 很大,然而每個對象的析構函數都無關痛癢,那麼一次次調用這些析構會哪數會降低效率,因此這裏利用value_type()獲得迭代器所指對象的型別,在利用__type_traits<T>判斷該型別的析構函數是否無關痛癢,如果是__true_type則什麼都不做,系統會採用內存直接處理操作,如果是__false_type才採用循環方式對每個對象進行析構。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章