tupleの構造関数

6046 ワード

tupleの構造関数


 template               class T5, class T6, class T7, class T8, class T9>
   class tuple :
    public detail::map_tuple_to_cons::type
   {
   public:
     typedef typename
       detail::map_tuple_to_cons::type
inherited;//ベースクラス
     typedef typename inherited::head_typehead_type;
//ベースクラスのhead_type(通常T 0、cons<>の定義を参照)
     typedef typename inherited::tail_typetail_type;
//ベースクラスのtail_type(一般的にはcons<>)
    
//次は11個の構造関数があります.私は2個しか与えません.他のクラスは同じです.パラメータの個数が増加しただけです.
tuple(){}//ここでもベースクラスのデフォルトコンストラクタを呼び出します
    
//access_traits<>の定義は後述する
    tuple(typename access_traits::parameter_typet0)
:inherited(t 0,detail::cnull(),//cnull関数はnull_を返しますtype()オブジェクト
detail::cnull(),detail::cnull(),//detail::cnull()をnull_と見なすことができるtype()
detail::cnull(),detail::cnull(),
detail::cnull(),detail::cnull(),
detail::cnull(),detail::cnull())
{ }
    tuple(typename access_traits::parameter_type t0,
        typename access_traits::parameter_type t 1)/パラメータt 1を追加
    : inherited(t0,t1, detail::cnull(), detail::cnull(),
                detail::cnull(),detail::cnull(), detail::cnull(),
                detail::cnull(),detail::cnull(), detail::cnull())
{ }
    ...
  };
コンストラクション関数のパラメータ型はaccess_traits<>が表現するには理由があり、その定義は以下の通りである.
   template 
struct access_traits {
     typedef const T& const_type;
     typedef T&non_const_type;
     typedef const typename boost::remove_cv::type& parameter_type;
};
先にremove_cvはT型が持つ可能性のあるconstまたはvolatile修飾子を削除し、
そしてconst修飾子と参照を表す記号&、parameter_type.parameter_typeはtuple構造関数でパラメータ型として用いられる.
例えば、T 0のテンプレートパラメータをintとするとtypenameaccess_traits::parameter_typeはconst int&.
なぜ参照型をパラメータ型として使用するのですか?
メリット:1、効率
2パラメータが参照の参照にならないようにする
参照をtuple内に直接保存したい場合は、T 0をint&に割り当てるとparameter_typeはアクセス_traitsは、次のような偏特化バージョンを用意しています.
   template  struct access_traits{
      typedef T& const_type;
      typedef T& non_const_type;
      typedef T¶meter_type;  
   };
注意:tupleが次のように定義できる理由も説明されています.
次のように使用できます.
  tuples(1,”345”);
アクセス:intj=std::get<0>(s);
std::tie(1, "aa", 2);
std::tuple<int&,string&, int&>

例:


次に、私たちの例に戻ると、tupleを具現化すると、この具現体の構造関数は次のようになります.
A  tuple(){}
B  tuple(const int& t0) :inherited(t0, detail::cnull(),...,detail::cnull()){}
C  tuple(const int& t0,const long& t1)
:inherited(t0,t1,detail::cnull(),...,detail::cnull())
{ }
D  tuple(const int& t0,const long& t1,const bool& t2)
  :inherited(t0,t1,t2,detail::cnull(),...,detail::cnull())
{ }
E  tuple(const int& t0,const long& t1,const bool& t2,const null_type& t3)
 : inherited(t0,t1,t2,detail::cnull(),..)
{}//これは使えません
...//その他のコンストラクション関数はこのように推す
以下の初期化方法があります.
tupleMyTuple;//OK、すべてのメンバーがデフォルトで初期化され、Aが呼び出されます.
tupleMyTuple(10);//OK、最初のメンバーは10に割り当てられ、他の2つのデフォルトは初期化され、Bが呼び出されます.
tupleMyTuple(10,10);//OK、第1の2番目のメンバーに値を割り当て、Cを呼び出す
tupleMyTuple(10,10,true);//OK、3人のメンバーに初期値を付与し、Dを呼び出す
このようにtupleを初期化するとします.
(1)与えられた初期化パラメータが十分である場合(すなわち、初期化パラメータが全て与えられている)に実パラメータがある場合は、実パラメータ初期化、すなわちhead(t)を用いる
tupleMyTuple(10,11,true);
tupleを呼び出すDコンストラクション関数が呼び出されます.
3つのパラメータをベースクラスに渡し、第1のcons<>はheadを10に割り当て、残りのパラメータをtailにすべて渡します.後者はcons<>で、headを11に割り当てます(この場合、最初のパラメータは11です).残りのtrueに後面の9つのnull_を加えます.typeはそのtail-cons(最内層のcons<>).consこの偏特化バージョンの構造関数はheadだけがtailメンバーを持っていないためユニークです.
パラメータが最内層cons<>に伝達されると、少なくとも尾のある9つのnull_に違いない.type.
cons<>コンストラクション関数の「搾取」を経て、最内層cons<>のコンストラクション関数が呼び出されるまで、与えられたN個のパラメータは1つしか残っていません(他にも9個のnull_typeがあります).
(2)与えられた初期化パラメータが足りない場合(すなわち、初期化パラメータが全て与えられない)
実パラメータがない場合はhead()を使用して初期化
このように書くとします.
tupleMyTuple(10);
これはtupleのBコンストラクション関数を呼び出し、後者はこの一意のパラメータの後に9つのnull_を追加します.typeはベースクラスに渡されます.
最外層のcons<>は、最外層のcons<>がheadを10に初期化する.
10個のnullをtypeはtailの構造関数に渡される.
【後者のheadはlong型データメンバーであるため、最初のパラメータnull_typeでlong headメンバーを初期化し、コンパイルエラーを引き起こす】cons<>に別の構造関数を提供する.
    template               class T6, class T7, class T8, class T9, class T10>
cons(const null_type&t 1,//受け入れられた最初のパラメータがnull_typeの場合
T2& t2,T3& t3, T4& t4, T5& t5,
            T6&t6, T7& t7, T8& t8, T9& t9, T10& t10 )
      : head (), tail (t2, t3, t4, t5,t6, t7, t8, t9, t10, detail::cnull())
     {}
初期化パラメータが「足りない」場合、cons<>のレイヤ(最後のレイヤ未満)で10個のパラメータがnull_だらけに「搾取」されます.typeは、cons<>のこのコンストラクション関数と一致し、head(t 1)ではなくheadをデフォルトで初期化します.
cons<>の偏特化バージョンにも似たようなバージョンがあります.
   cons(const null_type&,
       const null_type&, const null_type&, const null_type&,
       const null_type&, const null_type&, const null_type&,
       const null_type&, const null_type&, const null_type&)
  : head () {}