テンプレート (C++)Templates (C++)

テンプレートは、C++ での汎用のプログラミングの基礎です。Templates are the basis for generic programming in C++. 厳密に型指定された言語として C++ にはすべての変数を明示的にプログラマが宣言されている、またはコンパイラが推論し、特定の種類を持つ必要があります。As a strongly-typed language, C++ requires all variables to have a specific type, either explicitly declared by the programmer or deduced by the compiler. ただし、多くのデータ構造とアルゴリズムの種類にかかわらず同じに見えます。However, many data structures and algorithms look the same no matter what type they are operating on. これらの操作の種類のクラスや関数の操作を定義し、ユーザーがどのような具象型を指定できるテンプレートの有効化に取り組む必要があります。Templates enable you to define the operations of a class or function, and let the user specify what concrete types those operations should work on.

定義とテンプレートの使用Defining and using templates

テンプレートは、ユーザーはテンプレートのパラメーターを提供する引数に基づいた、コンパイル時に、通常の型または関数を生成するコンストラクトです。A template is a construct that generates an ordinary type or function at compile time based on arguments the user supplies for the template parameters. たとえば、このような関数テンプレートを定義できます。For example, you can define a function template like this:

template <typename T>
T minimum(const T& lhs, const T& rhs)
{
    return lhs < rhs ? lhs : rhs;
}

上記のコードが 1 つの型パラメーターを持つジェネリック関数のテンプレートについて説明しますT値を返し、パラメーター (lhs と rhs) の呼び出し元はこの型のすべて。The above code describes a template for a generic function with a single type parameter T, whose return value and call parameters (lhs and rhs) are all of this type. 型パラメーターは、最も一般的に使用すると同様が、規則の 1 つの大文字の文字で何も名前をことができます。You can name a type parameter anything you like, but by convention single upper case letters are most commonly used. Tテンプレート パラメーターは、 typenameキーワードは、このパラメーターは、型のプレース ホルダー。T is a template parameter; the typename keyword says that this parameter is a placeholder for a type. コンパイラでのすべてのインスタンスを交換して、関数が呼び出されると、Tされるか、ユーザーが指定したコンパイラによって推測された具象型引数を持つ。When the function is called, the compiler will replace every instance of T with the concrete type argument that is either specified by the user or deduced by the compiler. コンパイラは、クラスを生成しますまたは、テンプレートからの関数と呼びますプロセステンプレートのインスタンス化;。minimum<int>テンプレートをインスタンス化は、minimum<T>します。The process in which the compiler generates a class or function from a template is referred to as template instantiation; minimum<int> is an instantiation of the template minimum<T>.

他の場所で、ユーザーが int の特化したテンプレートのインスタンスを宣言できます。Get_a() と get_b() が int を返す関数であると仮定します。Elsewhere, a user can declare an instance of the template that is specialized for int. Assume that get_a() and get_b() are functions that return an int:

int a = get_a();
int b = get_b();
int i = minimum<int>(a, b);

ただし、これが関数テンプレートと、コンパイラの型を推測T引数から b、通常の関数と同じように呼び出すことができます。However, because this is a function template and the compiler can deduce the type of T from the arguments a and b, you can call it just like an ordinary function:

int i = minimum(a, b);

コンパイラには、その最後のステートメントが検出されると、新しい関数を生成 すべてのオカレンスTテンプレートでに置き換えられますint:When the compiler encounters that last statement, it generates a new function in which every occurrence of T in the template is replaced with int:

int minimum(const int& lhs, const int& rhs)
{
    return lhs < rhs ? lhs : rhs;
}

関数テンプレートで、コンパイラが型の推論を実行する方法のルールは、通常の関数の規則に基づいています。The rules for how the compiler performs type deduction in function templates are based on the rules for ordinary functions. 詳細については、次を参照してください。オーバー ロード解決の関数テンプレート呼び出しします。For more information, see Overload Resolution of Function Template Calls.

型パラメーターType parameters

minimumなお、上記のテンプレート型パラメーター T定数と参照修飾子が追加される関数呼び出しのパラメーターで使用されるまで任意の方法では修飾されません。In the minimum template above, note that the type parameter T is not qualified in any way until it is used in the function call parameters, where the const and reference qualifiers are added.

型パラメーターの数に事実上制限はありません。There is no practical limit to the number of type parameters. 複数のパラメーターをコンマで区切ります。Separate multiple parameters by commas:

template <typename T, typename U, typename V> class Foo{};

キーワードクラスと等価typenameこのコンテキストでします。The keyword class is equivalent to typename in this context. 前の例として表すことができます。You can express the previous example as:

template <class T, class U, class V> class Foo{};

省略記号演算子 (...) を使用して、任意の数の 0 個以上の型パラメーターを受け取るテンプレートを定義できます。You can use the ellipses operator (...) to define a template that takes an arbitrary number of zero or more type parameters:

template<typename... Arguments> class vtclass;

vtclass< > vtinstance1;
vtclass<int> vtinstance2;
vtclass<float, bool> vtinstance3;

任意の組み込みまたはユーザー定義型は、型引数として使用できます。Any built-in or user-defined type can be used as a type argument. Int、double 型、文字列を格納する標準ライブラリで std::vector を使用するなど、MyClass、MyClass const *、MyClass (& a)。For example, you can use std::vector in the Standard Library to store ints, doubles, strings, MyClass, const MyClass*, MyClass&. テンプレートを使用する場合は、重要な制限は、型引数が型パラメーターに適用されるすべての操作をサポートする必要があります。The primary restriction when using templates is that a type argument must support any operations that are applied to the type parameters. たとえば、最小値と呼んで MyClass を使用して、この例のように。For example, if we call minimum using MyClass as in this example:

class MyClass
{
public:
    int num;
    std::wstring description;
};

int main()
{
    MyClass mc1 {1, L"hello"};
    MyClass mc2 {2, L"goodbye"};
    auto result = minimum(mc1, mc2); // Error! C2678
}

MyClass がのオーバー ロードを提供しないために、コンパイラ エラーが発生、< 演算子。A compiler error will be generated because MyClass does not provide an overload for the < operator.

このような制限を適用するテンプレートを定義できますが、特定のテンプレートのすべての型引数が、同じオブジェクトの階層に属する固有の要件はありません。There is no inherent requirement that the type arguments for any particular template all belong to the same object hierarchy, although you can define a template that enforces such a restriction. テンプレートでオブジェクト指向の手法を組み合わせることができます。たとえば、格納できます派生 * ベクターに<ベース*>。You can combine object-oriented techniques with templates; for example, you can store a Derived* in a vector<Base*>. 引数はポインターである必要がありますに注意してください。Note that the arguments must be pointers

vector<MyClass*> vec;
   MyDerived d(3, L"back again", time(0));
   vec.push_back(&d);

   // or more realistically:
   vector<shared_ptr<MyClass>> vec2;
   vec2.push_back(make_shared<MyDerived>());

ベクターと他の標準ライブラリ コンテナーの要素に加えたの基本的な要件TですTコピー代入とコピー構築します。The basic requirements that vector and other standard library containers impose on elements of T is that T be copy-assignable and copy-constructible.

非型パラメーターNon-type parameters

C# や Java などの他の言語でジェネリック型とは異なりは、C++ テンプレートは、値パラメーターとも呼ばれます。 非型パラメーターをサポートします。Unlike generic types in other languages such as C# and Java, C++ templates support non-type parameters, also called value parameters. たとえば、この例では、標準ライブラリで std::array クラスと同様に、配列の長さを指定する定数整数値を行うことができます。For example, you can provide a constant integral value to specify the length of an array, as with this example that is similar to the std::array class in the Standard Library:

template<typename T, size_t L>
class MyArray
{
    T arr[L];
public:
    MyArray() { ... }
};

テンプレート宣言の構文に注意してください。Note the syntax in the template declaration. Size_t 値では、コンパイル時にテンプレート引数として渡され、定数または式を constexpr にする必要があります。The size_t value is passed in as a template argument at compile time and must be constant or a constexpr expression. 次のように使用します。You use it like this:

MyArray<MyClass*, 10> arr;

非型パラメーターとしてでその他のポインターと参照を含む値を渡すことができます。Other kinds of values including pointers and references can be passed in as non-type parameters. たとえば、関数または関数オブジェクト、テンプレート コード内でいくつかの操作をカスタマイズするにポインターに渡します。For example, you can pass in a pointer to a function or function object to customize some operation inside the template code.

テンプレート パラメーターとしてテンプレートTemplates as template parameters

テンプレートには、テンプレート パラメーターを指定できます。A template can be a template parameter. この例で MyClass2 が 2 つのテンプレート パラメーター: typename パラメーター Tとテンプレート パラメーター Arr:In this example, MyClass2 has two template parameters: a typename parameter T and a template parameter Arr:

template<typename T, template<typename U, int I> class Arr>
class MyClass2
{
    T t; //OK
    Arr<T, 10> a;
    U u; //Error. U not in scope
};

Arrパラメーター自体には、本文がない、そのパラメーター名は必要ありません。Because the Arr parameter itself has no body, its parameter names are not needed. 実際を参照するとエラーがArrの typename またはクラス内のパラメーター名からの本文MyClass2します。In fact, it is an error to refer to Arr's typename or class parameter names from within the body of MyClass2. このため、 Arrのこの例で示すように、型パラメーター名を省略できます。For this reason, Arr's type parameter names can be omitted, as shown in this example:

template<typename T, template<typename, int> class Arr>
class MyClass2
{
    T t; //OK
    Arr<T, 10> a;
};

既定のテンプレート引数Default template arguments

クラスと関数テンプレートは、既定の引数でことができます。Class and function templates can have default arguments. テンプレートのままにすることができます、既定の引数がある使用すると、指定されません。When a template has a default argument you can leave it unspecified when you use it. たとえば、std::vector テンプレートでは、アロケーターの既定の引数があります。For example, the std::vector template has a default argument for the allocator:

template <class T, class Allocator = allocator<T>> class vector;

ほとんどの場合は、このようなベクトルを使用するようで既定の std::allocator クラスは、許容されます。In most cases the default std::allocator class is acceptable, so you use a vector like this:

vector<int> myInts;

かどうか必要に応じて指定することがカスタム アロケーターは、このような。But if necessary you can specify a custom allocator like this:

vector<int, MyAllocator> ints;

テンプレート引数が複数ある場合、最初の既定の引数の後は、すべての引数に既定の引数が必要です。For multiple template arguments, all arguments after the first default argument must have default arguments.

パラメーターを持つ内容はすべて既定のテンプレートを使用する場合は、空の山かっこを使用します。When using a template whose parameters are all defaulted, use empty angle brackets:

template<typename A = int, typename B = double>
class Bar
{
    //...
};
...
int main()
{
    Bar<> bar; // use all default type arguments
}

テンプレートの特殊化Template specialization

場合によっては、不可能であるか、または任意の型に対して正確に同じコードを定義するテンプレートに望ましくはありません。In some cases, it isn’t possible or desirable for a template to define exactly the same code for any type. たとえば、型引数がポインター、または、std::wstring または特定の基本クラスから派生した型の場合にのみに実行されるコード パスを定義することもできます。For example, you might wish to define a code path to be executed only if the type argument is a pointer, or a std::wstring, or a type derived from a particular base class. このような場合を定義できますを特殊化の特定の種類のテンプレート。In such cases you can define a specialization of the template for that particular type. ユーザーは、その型でテンプレートをインスタンス化、ときにコンパイラは、クラスを生成する、特殊化を使用し、他のすべての種類では、コンパイラがより一般的なテンプレートを選択します。When a user instantiates the template with that type, the compiler uses the specialization to generate the class, and for all other types, the compiler chooses the more general template. すべてのパラメーターが特殊化された特殊化は特殊化を完了します。Specializations in which all parameters are specialized are complete specializations. 呼び出されたパラメーターの一部が特殊化された場合のみ、部分的特殊化します。If only some of the parameters are specialized, it is called a partial specialization.

template <typename K, typename V>
class MyMap{/*...*/};

// partial specialization for string keys
template<typename V>
class MyMap<string, V> {/*...*/};
...
MyMap<int, MyClass> classes; // uses original template
MyMap<string, MyClass> classes2; // uses the partial specialization

テンプレートには、それぞれの特殊化された型パラメーターが一意に任意の数の特殊化のことができます。A template can have any number of specializations as long as each specialized type parameter is unique. クラス テンプレートのみを部分的に特殊化することがあります。Only class templates may be partially specialized. テンプレートのすべての完全および部分的な特殊化は、元のテンプレートと同じ名前空間で宣言する必要があります。All complete and partial specializations of a template must be declared in the same namespace as the original template.

詳細については、次を参照してください。テンプレートの特殊化します。For more information, see Template Specialization.