c++templateのtrait技法まとめ

9876 ワード

Trait技法の最初の目的はテンプレートパラメータを管理することであり、テンプレートにはいくつかのパラメータが必要になる場合があるが、main parametersと密接に関連しているパラメータがあることが多い.この場合、traitテクニックを使用して、いくつかの主要なテンプレートパラメータから対応するsecondary template argumentを導出し、デフォルトのテンプレートパラメータの形式でテンプレートに表示することができる.実際に使用するtraitテクニックの例は、プログラムの効率を効果的に向上させることが多いので、STLと結びつけてtraitの実際の運用についてお話しします.
1、SGI STL中の_type_traits
タイプは大まかに2つあります.1つはclassでカプセル化され、そのコピーには時間がかかります.例えば、深さのコピーが必要で、safe copyingが必要です.つまり、構造関数を呼び出してコピーを完了する必要があります.もう1つはいわゆるPOD(plain old data)で、一般的にbuild-inタイプかc式のstructタイプで、このタイプはメモリブロックをコピーしてコピーするだけでいいので、bitwise copyingやtrival construct/deconstruct/copy/assignmentの概要があります.
SGI STLで使用_type_traitsは、コンパイル中にオブジェクトをコピーするかmemcpyを直接呼び出すかを決定し、効率を向上させることができます.SGI STLのソースコードを見てください.
[cpp] view plain copy print ?
struct __true_type {};
  • struct __false_type {};

  • template //primariy template

  • struct __type_traits {
  • typedef __true_type this_dummy_member_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;

  • };
  • __STL_TEMPLATE_NULL struct __type_traits {//full specialization

  • 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;
  • };

  • __STL_TEMPLATE_NULL struct __type_traits {
  • 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;

  • };
    struct __true_type {};
    struct __false_type {};
    
    template <class type>   //primariy template
    struct __type_traits { 
       typedef __true_type     this_dummy_member_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;
    };
    __STL_TEMPLATE_NULL struct __type_traits<char> { //full specialization
       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;
    };
    __STL_TEMPLATE_NULL struct __type_traits<int> {
       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;
    };

    [cpp] view plain copy print ?
    ......//他のbuild-inタイプに対する特化
    ......//    build-in     

    次に、使い方を見てみましょうtype_trairt:
    [cpp] view plain copy print ?
    template
  • inline ForwardIterator __uninitialized_copy(InputIterator first, InputIterator last,

  • ForwardIterator result, T*) {
  • typedef typename __type_traits::is_POD_type is_POD;

  • return __uninitialized_copy_aux(first, last, result, is_POD());
  • }

  • template inline ForwardIterator
  • __uninitialized_copy_aux(InputIterator first, InputIterator last,

  • ForwardIterator result, __true_type) {
  • return copy(first, last, result); //STLアルゴリズムcopyには乾坤があり、PODタイプに対してmemmoveを呼び出し、iterator_も含まれている.traitの使用
  • }
  • template

  • ForwardIterator __uninitialized_copy_aux(InputIterator first, InputIterator last,
  • ForwardIterator result, __false_type) {

  • ForwardIterator cur = result;
  • for ( ; first != last;++first,++cur)

  • construct(&*cur, *first);
  • return cur;

  • }
  • }
  • template <class InputIterator, class ForwardIterator, class T>
    inline ForwardIterator __uninitialized_copy(InputIterator first, InputIterator last,
                         ForwardIterator result, T*) {
      typedef typename __type_traits<T>::is_POD_type is_POD;
      return __uninitialized_copy_aux(first, last, result, is_POD());
    }
    template <class InputIterator, class ForwardIterator> inline ForwardIterator 
    __uninitialized_copy_aux(InputIterator first, InputIterator last,
                             ForwardIterator result, __true_type) {
      return copy(first, last, result); //STL   copy      ,  POD  ,  memmove,   iterator_trait   
    }
    template <class InputIterator, class ForwardIterator>
    ForwardIterator __uninitialized_copy_aux(InputIterator first, InputIterator last,
                             ForwardIterator result, __false_type) {
      ForwardIterator cur = result;
        for ( ; first != last; ++first, ++cur)
          construct(&*cur, *first);
        return cur;
      }
    }
    

    その他uninitialized_fill、
    uninitialized_fill_nも似ている.また、「C++template」のCSMTraitsもtraitの強さを説明しています.
    2、STLのiterator_traits
    iterator_traitsは、反復器のvalue type、different type、reference type、pointer type、iterator_を定義します.categoryタイプは、最後の1つだけを言います.
    [cpp] view plain copy print ?
    struct input_iterator_tag {};
  • struct output_iterator_tag {};

  • struct forward_iterator_tag :public input_iterator_tag {};
  • struct bidirectional_iterator_tag : public forward_iterator_tag {};

  • struct random_access_iterator_tag :public bidirectional_iterator_tag {};
    struct input_iterator_tag {};
    struct output_iterator_tag {};
    struct forward_iterator_tag : public input_iterator_tag {};
    struct bidirectional_iterator_tag : public forward_iterator_tag {};
    struct random_access_iterator_tag : public bidirectional_iterator_tag {};

    [cpp] view plain copy print ?
    template struct input_iterator {
  • typedef input_iterator_tag iterator_category;

  • };
  • struct output_iterator {

  • typedef output_iterator_tag iterator_category;
  • };

  • template struct forward_iterator {
  • typedef forward_iterator_tag iterator_category;

  • };
  • template struct bidirectional_iterator {

  • typedef bidirectional_iterator_tag iterator_category;
  • };

  • template struct random_access_iterator {
  • typedef random_access_iterator_tag iterator_category;

  • };
    template <class T, class Distance> struct input_iterator {
      typedef input_iterator_tag iterator_category;
    };
    struct output_iterator {
      typedef output_iterator_tag iterator_category;
    };
    template <class T, class Distance> struct forward_iterator {
      typedef forward_iterator_tag iterator_category;
    };
    template <class T, class Distance> struct bidirectional_iterator {
      typedef bidirectional_iterator_tag iterator_category;
    };
    template <class T, class Distance> struct random_access_iterator {
      typedef random_access_iterator_tag iterator_category;
    };

    [cpp] view plain copy print ?
    //iterator_traitsの使用
    //iterator_traits   

    [cpp] view plain copy print ?
    template      
  • inline void advance(InputIterator& i, Distance n) {

  • __advance(i, n, iterator_traits::iterator_category());//一時的なxx_を作成iterator_tagオブジェクト
  • }

  • template
  • inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {

  • while (n--)++i;
  • }

  • template
  • inline void __advance(BidirectionalIterator& i, Distance n,

  • bidirectional_iterator_tag) {
  • if (n >= 0)

  • while (n--)++i;
  • else

  • while (n++) --i;
  • }

  • template
  • inline void __advance(RandomAccessIterator& i, Distance n,

  • random_access_iterator_tag) {
  • i += n;

  • }
  •   

  •   

  • 3、STLのchar_traits


  • traitに関連するpolicyテクニックもあり、traitはメインテンプレートパラメータから密接に関連するタイプや定数などの情報を導出することに偏り、policyは関数などの行為面の情報に偏ります.traitとpolicyの境界はあいまいで、実際にはproperty traitとpolicy trairtの概念もある本もある.これにより、policyは定義されたアルゴリズム(関数)に似ており、主テンプレートパラメータと密接な論理的関連がないことがわかる.




  • 参考書:『STLソース剖析』

  • 《C++template》