C++11特性可変パラメータテンプレート

4815 ワード

可変パラメータテンプレート本稿では,可変パラメータテンプレートの基本概念と用法を紹介し,cppreferenceの内容を多く参考し,その整理と総括と言える.
  • バックグラウンド
  • テンプレートの形参加実参とは何ですか?
  • テンプレート形パラメータ
  • 関数テンプレートのパラメータパケット
  • 形参照展開
  • 用法
  • 展開可能位置
  • まとめ
  • 背景
    c++11特性は、可変テンプレートパラメータという特性を導入し、不定個数パラメータを含むテンプレートクラスとテンプレートパラメータを実現することができる.次のコード:変数テンプレートクラスは次のとおりです.
    //       
    template 
    struct Tuple {};
    Tuple<> t0;           // Types      
    Tuple t1;        // Types       :int
    Tuple t2; // Types       :int   float
    Tuple<0> error;       //   :0     
    

    変数テンプレート関数は次のとおりです.
    template 
    void f(Types ... args);
    f();       // OK:args      
    f(1);      // OK:args       :int
    f(2, 1.0); // OK:args       :int   double
    

    では、パラメトリッククラスとパラメトリック関数はどのように使用すればいいのでしょうか.この文章はあなたの変参の解テンプレートクラスとテンプレート関数を持って、どのように使用するかを教えます.
    テンプレートのシェイプ参加実参とは何ですか?
    テンプレートパラメータは、関数内の形参加実パラメータと同様に、形参加実パラメータに分けることができます.形パラメータは変数宣言であり、実パラメータは変数の具体的な値です.テンプレート内のパラメータはタイプ(または値)宣言で、実パラメータはあなたが入力したいタイプです.cppreferenceを参考にして、簡単に言えば以下のようになります.
  • テンプレートパラメータ
    template <      >   	
    
  • テンプレート実参
    Tuple t1;        // Types       :int
    
  • テンプレートシェイプ
    テンプレートの形が実参に関与する概念を知ってから、形参のパケット--形参パケットを理解する.
    テンプレートパラメータパッケージは、0以上のテンプレート実パラメータ(非タイプ、タイプ、またはテンプレート)を受け入れるテンプレートパラメータです.関数テンプレートパラメータパッケージは、ゼロ以上の関数実パラメータを受け入れる関数パラメータです.少なくとも1つのパラメトリックパッケージのテンプレートを変パラメトリックテンプレートと呼ぶ.cppreference
    テンプレート形パラメータ(別名テンプレート、クラステンプレート、変数テンプレート、および関数テンプレート形パラメータのリストに表示される)は、次のように定義されます.
    タイプ…Args(オプション)(1)typename|class…Args(オプション)(2)template<パラメータリスト>typename(C++17)|class…Args(オプション)——cppreference
  • オプションの名前の非タイプテンプレート形パケット
  • オプションの名前付きタイプテンプレートパッケージ
  • オプションの名前のテンプレートテンプレートパッケージ
  • 以上は公式の定義です.簡単に言えば、テンプレートクラスまたはテンプレート関数のテンプレート宣言は次のようになります.
    template  // typename ... Types     
    struct Tuple {};
    
    template // typename ... Types     
    void f(Types ... args);
    

    関数テンプレートのパラメータパッケージ
    テンプレート関数のパラメータはどのように書きますか?関数テンプレートパラメータパッケージは次のように定義されます.
    Args...args(オプション)
    コード:
    template 
    void f(Types ... args); // Types ... args          
    

    シェイプの展開
    使用法
    関数またはクラスでシェイプパケットを使用する場合は、まず展開する必要があります.形式;
    モード...
    次のように定義します.
    パターンの後に省略記号が表示され、少なくとも1つのシェイプパケットの名前が少なくとも1回表示され、0以上のカンマで区切られたパターンインスタンスに展開され、シェイプパケットの名前がパケット内の各要素に順番に置き換えられます.
    次のコードがあります.
    //   1
    template void f(Us... pargs) {}
    template void g(Ts... args) {
        f(&args...); // “&args...”     
                     // “&args”     
    }
    g(1, 0.2, "a"); // Ts... args     int E1, double E2, const char* E3
                    // &args...     &E1, &E2, &E3
                    // Us...     int* E1, double* E2, const char** E3
    

    コード中のf(&args...)f(&E1, &E2, &E3)に展開され、f(&args)...に変更されるとf(&E1),f(&E1),f(&E1)に展開され、もちろんコンパイルエラーが発生します.次のコードもあります.
    //   2
    template struct Tuple {};
    template struct Pair {};
     
    template struct zip {
        template struct with {
            typedef Tuple...> type;
    //        Pair...     
    //        Pair    
        };
    };
     
    typedef zip::with::type T1;
    // Pair...    
    // Pair, Pair 
    // T1   Tuple, Pair>
    

    展開可能な場所
  • 関数実パラメトリックリスト
  • 有括弧初期化器
  • 括弧で囲む初期化器
  • テンプレート実パラメトリックリスト
  • 関数パラメータリスト
  • テンプレートパラメータリスト
  • ベースクラス説明子とメンバーイニシエータリスト
  • lamda関数スナップリスト
  • テクニック:再帰パッケージ展開は、再帰呼び出しでテンプレート関数を定義できます.
    template 
    T Sum(T data) {
        return data;
    }
    
    template 
    T Sum(T data, Args... args) {
        return data + Sum(args...);
    }
    
    int main() {
        std::cout << Sum(1, 2, 3, 4) << std::endl;  //    10
        std::cout << Sum(1) << std::endl;   //    1
        return 0;
    }
    

    まとめ
    パラメータテンプレートには、次の手順があります.
  • 形参照パッケージ定義template
  • 関数テンプレートの場合、関数パラメータ定義f(Args ... args)
  • 関数またはクラス内部パケット展開:f(args...)またはf(args)...