Share via


テンプレートの仕様

 

template 宣言は、一連のパラメーター化されたクラスまたは関数を指定します。

構文

template < template-parameter-list > declaration

解説

template-parameter-list はテンプレート パラメーターのコンマ区切りのリストです。これは、テンプレート本体で使用される型 (classidentifiertypenameidentifier、または template < template-parameter-list > class identifier の形式) または非型パラメーターです。テンプレート パラメーターの構文は次のいずれかです。

parameter-declaration
class identifier [ = typename ] 
typename identifier [ = typename ]
template < template-parameter-list > class [identifier][= name]

通常のクラスをインスタンス化するのと同様に、クラス テンプレートをインスタンス化できますが、テンプレート引数を山かっこ (<>) で囲む必要があります。これらのテンプレート引数は、テンプレート引数リストにクラスまたは typename キーワードが含まれる場合は任意の型、引数が非型引数である場合は適切な型の値にできます。関数テンプレートを呼び出すために必要な特別な構文はありませんが、関数の引数からテンプレート パラメーターを推測できない場合、山かっことテンプレート引数が必要になることがあります。

template-parameter-list は、後に続くコードのどの部分が変化するかを指定するテンプレート関数で使用されるパラメーターのリストです。次に例を示します。

template< class T, int i > class MyStack...

この場合、テンプレートは 1 つの型 (class T) と定数パラメーター (int i) を受け取ることができます。テンプレートは、インスタンス化で型 T と定数整数 i を使用します。MyStack 宣言の本体で、T 識別子を参照する必要があります。

テンプレート宣言自体はコードを生成せず、クラスや関数のファミリを指定します。それらが他のコードによって参照されたときに、1 つまたは複数のクラスや関数が生成されます。

テンプレート宣言は、グローバル スコープ、名前空間スコープ、またはクラス スコープを持ちます。これらは、関数の内部で宣言することはできません。

次の例は、型パラメーター T と非型テンプレート パラメーター i を持つクラス テンプレートの定義、宣言、およびインスタンス化を示しています。

// template_specifications1.cpp
template <class T, int i> class TestClass 
{
public:
   char buffer[i];
   T testFunc(T* p1 );
};

template <class T, int i>
T TestClass<T,i>::testFunc(T* p1) 
{
    return *(p1++)
};

// To create an instance of TestClass
TestClass<char, 5> ClassInst;
int main()
{
}

非型テンプレート引数

非型テンプレート パラメーターは、整数、列挙体、ポインター、参照、またはメンバー型へのポインターである必要があり、コンパイル時には定数である必要があります。これらは const または volatile 型として指定できます。浮動小数点値は、テンプレート パラメーターとして使用できません。クラス、構造体、または共用体型のオブジェクトは非型テンプレート パラメーターとして使用できません。ただし、これらのオブジェクトへのポインターは使用できます。非型テンプレート パラメーターとして渡された配列はポインターに変換されます。非型パラメーターとして渡された関数は、関数ポインターとして扱われます。文字列リテラルは、テンプレート パラメーターとして許可されません。

テンプレート宣言での typename の使用

typename キーワードは、テンプレート パラメーター リストで利用できます。次のテンプレート宣言は同じです。

template< class T1, class T2 > class X...
template< typename T1, typename T2 > class X...

テンプレート パラメーターの既定の引数

クラス テンプレートには、既定の引数を設定できます。指定するには、= 記号を使用し、その後に既定の型または値を続けます。関数テンプレートには、既定の引数を指定できません。詳細については、「クラス テンプレートの既定の引数」を参照してください。

template<typename Type> class allocator {};
template<typename Type, 
   typename Allocator = allocator<Type> > class stack 
{
};
stack<int> MyStack;

テンプレート パラメーターの再利用

テンプレート パラメーターは、テンプレート パラメーター リスト内で再利用できます。たとえば、次のようなコードを記述できます。

// template_specifications2.cpp

class Y 
{
};
template<class T, T* pT> class X1 
{
};
template<class T1, class T2 = T1> class X2 
{
};

Y aY;

X1<Y, &aY> x1;
X2<int> x2;

int main()
{
}

テンプレート パラメーターとしてのテンプレート

テンプレート パラメーターは、それ自体がテンプレートである可能性があります。この構造では、引数自体がテンプレートであり、テンプレートから構築されたクラスであってはなりません。次の例では、使用されることがありえないため、テンプレートのテンプレート パラメーターの名前 A は省略できます。

// template_specifications3.cpp
#include <stdio.h>

template <class T> struct str1
{
   T t;
};

template <template<class A> class T> struct str2
{
    T<int> t;
};

int main()
{
    str2<str1> mystr2;
    mystr2.t.t = 5;
    printf_s("%d\n", mystr2.t.t);
}

出力

5

テンプレート パラメーターとしての参照

Visual Studio .NET 2003 では、非型テンプレート パラメーターとして参照を使用する機能が導入されました。これは、以前のバージョンでは許可されていませんでした。

// references__supported_as_nontype_template_parameters.cpp
#include <stdio.h>

extern "C" int printf_s(const char*,...);
template <int & ri> struct S
{
   S()
   {
      printf_s("ri is %d\n", ri);
   }

   ~S()
   {
      printf_s("ri is %d\n", ri);
   }
};

int i = 1;

int main()
{
   S<i> s;
   i = 0;
}

出力

ri is 1
ri is 0

入れ子になったテンプレート インスタンス

Visual Studio 2005 より前のバージョンの Visual Studio では、入れ子になったテンプレート インスタンスの宣言時に、テンプレート パラメーター リストの間に空白を挿入する必要がありました。次の構文が許されるようになりました。

// template_specifications4.cpp 

template <typename T> 
class A
{
};

template <int n> 
class B 
{
};

int main() 
{
   A<B<22>>();
}

参照

テンプレート
C++ キーワード