C++のテンプレートと汎用プログラミング(一、テンプレート定義)


引用する
テンプレートに接触する前に、比較的サイズの関数を作成する場合は、次のように書きます.
   int compare(const string &v1, const string &v2)     {         if (v1 < v2) return -1;         if (v2 < v1) return 1;         return 0;     }
     int compare(const double &v1, const double &v2)     {         if (v1 < v2) return -1;         if (v2 < v1) return 1;         return 0;     }
これらの関数はほぼ同じで、それらの間の唯一の違いはパラメータのタイプであり、各関数の関数体は同じである.
この方法の欠点は,各関数が1つのデータ型にのみ適用され,新しいデータ型に遭遇すると,新しい関数を追加する必要があることである.
すべてのデータ型に適用できるテクノロジーはありますか?技術の革新は人間の怠惰に源を発し、ちょうどC++は私たちにこのような技術--関数テンプレートを提供してくれた.
 
関数テンプレートの動作原理
関数テンプレートはタイプとは独立した関数で、コンパイラはコンパイル中にプログラマが提供した実際のパラメータタイプに基づいてパラメータを置き換え、置き換えたコードを実際のパラメータで直接記述したコードのようにします.
 
関数テンプレートの定義
テンプレート定義はキーワードtemplateで始まり、テンプレートパラメータテーブルに続き、テンプレートパラメータテーブルはカッコで囲まれた1つ以上のテンプレートパラメータのリストであり、パラメータ間はカンマで区切られ、後で私たちが普段書いた関数宣言に続き、唯一の違いはパラメータタイプが実際の意味のないタイプにすぎないことです.テンプレートパラメータテーブルを空にすることはできません.
    //implement strcmp-like generic compare function    //returns 0 if the values are equal, 1 if v1 is larger, -1 if v1 is smaller     template      int compare(const T &v1, const T &v2)     {         if (v1 < v2) return -1;         if (v2 < v1) return 1;         return 0;     }
 
関数テンプレートの使用
     int main ()     {        //T is int;        //compiler instantiates int compare(const int&, const int&)         cout << compare(1, 0) << endl;        //T is string;        //compiler instantiates int compare(const string&, const string&)         string s1 = "hi", s2 = "world";         cout << compare(s1, s2) << endl;         return 0;     }
inline関数テンプレート
    //ok: inline specifier follows template parameter list     template inline T min(const T&, const T&);    //error: incorrect placement of inline specifier     inline template T min(const T&, const T&);
クラステンプレートの定義
template
class Queue {     public:         Queue ();               //default constructor         Type &front ();         //return element from head of Queue         const Type &front () const;         void push (const Type &);//add element to back of Queue         void pop();             //remove element from head of Queue         bool empty() const;     //true if no elements in the Queue     private:        //...     };
クラステンプレートの使用
     Queue qi;                //Queue that holds ints     Queue< vector> qc;   //Queue that holds vectors of doubles     Queue qs;             //Queue that holds strings
 
テンプレートパラメータ
1、テンプレートパラメータは、タイプを表すタイプパラメータであってもよく、定数式を表す非タイプパラメータであってもよい.タイプパラメータの場合、このパラメータは未知のタイプを表し、非タイプパラメータの場合、未知の値であることがわかります.
2、関数パラメータのように、プログラマがテンプレートパラメータのために選択した名前には本質的な意味がありません.
3、テンプレートパラメータが表すタイプまたは値を使用する場合は、対応するテンプレートパラメータと同じ名前を使用できます.
4、テンプレートパラメータの名前は、テンプレートパラメータとして宣言した後、テンプレート宣言または定義の末尾まで使用できます.
5、テンプレートパラメータは通常の名前マスク規則に従う.グローバル役割ドメインで宣言されたオブジェクト、関数、またはタイプと同じ名前のテンプレートパラメータは、グローバル名をマスクします.
     typedef double T;     template T calc(const T &a, const T &b)     {         //tmp has the type of the template parameter T         //not that of the global typedef          T tmp = a;         //...          return tmp;}6、テンプレート形参として使用する名前はテンプレート内部で再利用できない
     template T calc(const T &a, const T &b)     {         typedef double T;//error: redeclares template parameter T         T tmp = a;        //...         return tmp;}7、関数パラメータの名前を再利用できるように、テンプレートパラメータの名前も異なるテンプレートで再利用できます.
     // ok: reuses parameter type name across different templates
     template <class T> T calc (const T&, const T&) ;
     template <class T> int compare(const T&, const T&) ;
8、           ,             。               
    // declares compare but does not define it
     template <class T> int compare(const T&, const T&) ;
9、                  class   typename,             
    // error: must precede U by either typename or class
     template <typename T, U> T calc (const T&, const U&) ;

size_type , :

     template <class Parm, class U>
     Parm fcn(Parm* array, U value)
     {
         typename Parm::size_type * p; // ok: declares p to be a pointer
     }
 
       
                ,             。  ,           
array_init                             。          ,
         
     // initialize elements of an array to zero
     template <class T, size_t N> void array_init(T (&parm)[N])
     {
         for (size_t i = 0; i != N; ++i) {
             parm[i] = 0;
         }
     }
      
1、       ,                 
2、