ジェネリックとテンプレート (C++/CLI)Generics and Templates (C++/CLI)

ジェネリックとテンプレートは、どちらもパラメーター化された型のサポートを提供する言語機能です。Generics and templates are both language features that provide support for parameterized types. ただし、それらは同じではなく、用途が異なっています。However, they are different and have different uses. このトピックでは、多くの相違点について、その概要を説明します。This topic provides an overview of the many differences.

詳細については、「Windows ランタイムおよびマネージド テンプレート (C++/CLI および C++/CX)」を参照してください。For more information, see Windows Runtime and Managed Templates.

テンプレートとジェネリックの比較Comparing Templates and Generics

ジェネリックと C++ テンプレートの重要な相違点:Key differences between generics and C++ templates:

  • ジェネリックは、実行時にそれらが型に置き換えられるまではジェネリックのままです。Generics are generic until the types are substituted for them at runtime. テンプレートはコンパイル時に特殊化され、実行時にパラメーター化されていない型のままではありません。Templates are specialized at compile time so they are not still parameterized types at runtime

  • 共通言語ランタイムでは、特に MSIL でジェネリックをサポートします。The common language runtime specifically supports generics in MSIL. このランタイムではジェネリック型が認識されるため、ジェネリック型を含むアセンブリの参照時に、ジェネリック型を特定の型に置き換えることができます。Because the runtime knows about generics, specific types can be substituted for generic types when referencing an assembly containing a generic type. これに対し、テンプレートでは、コンパイル時に通常の型に解決され、他のアセンブリではその型を特殊化できない場合があります。Templates, in contrast, resolve into ordinary types at compile time and the resulting types may not be specialized in other assemblies.

  • 2 つの異なるアセンブリで同じ型引数に特殊化されたジェネリックは、同じ型になります。Generics specialized in two different assemblies with the same type arguments are the same type. 2 つの異なるアセンブリで同じ型引数に特殊化されたテンプレートは、実行時に異なる型とみなされます。Templates specialized in two different assemblies with the same type arguments are considered by the runtime to be different types.

  • ジェネリックは、すべての参照型の引数で使用される単一の実行可能コードとして生成されます (これは値型には当てはまりません。値型には、値型ごとに独自の実装があります)。Generics are generated as a single piece of executable code which is used for all reference type arguments (this is not true for value types, which have a unique implementation per value type). JIT コンパイラではジェネリックが認識されるるため、型引数として使用される参照型または値型のコードを最適化できます。The JIT compiler knows about generics and is able to optimize the code for the reference or value types that are used as type arguments. テンプレートは、それぞれの特殊化に対して、個別のランタイム コードを生成します。Templates generate separate runtime code for each specialization.

  • ジェネリックでは、template <int i> C {} などのテンプレートの型パラメーターではないパラメーターは許可されません。Generics do not allow non-type template parameters, such as template <int i> C {}. テンプレートでは可能です。Templates allow them.

  • ジェネリックでは、明示的な特殊化 (特定の型用のテンプレートのカスタム実装) は許可されません。Generics do not allow explicit specialization (that is, a custom implementation of a template for a specific type). テンプレートでは可能です。Templates do.

  • ジェネリックでは、部分的な特殊化 (型引数のサブセットのカスタム実装) は許可されません。Generics do not allow partial specialization (a custom implementation for a subset of the type arguments). テンプレートでは可能です。Templates do.

  • ジェネリックでは、ジェネリック型の基底クラスとしての型パラメーターは許可されません。Generics do not allow the type parameter to be used as the base class for the generic type. テンプレートでは可能です。Templates do.

  • テンプレートでは、テンプレート対テンプレートのパラメーター (例: template<template<class T> class X> class MyClass) をサポートしますが、ジェネリックではサポートしません。Templates support template-template parameters (e.g. template<template<class T> class X> class MyClass), but generics do not.

テンプレートとジェネリックの組み合わせCombining Templates and Generics

ジェネリックの基本的な相違点には、テンプレートとジェネリックを組み合わせたアプリケーションをビルドするという言外の意味があります。The basic difference in generics has implications for building applications that combine templates and generics. たとえば、テンプレートを他の言語にジェネリックとして公開するためのジェネリック ラッパーを作成したいテンプレート クラスがあるとします。For example, suppose you have a template class that you want to create a generic wrapper for to expose that template to other languages as a generic. テンプレートではコンパイル時に型パラメーターが必要ですが、ジェネリックでは型は実行時まで解決されないため、テンプレートに渡される型パラメーターをジェネリックで使用することはできません。You cannot have the generic take a type parameter that it then passes though to the template, since the template needs to have that type parameter at compile time, but the generic won't resolve the type parameter until runtime. コンパイル時にテンプレートを展開して実行時にインスタンス化できる任意のジェネリック型にする方法はないため、ジェネリックの中にテンプレートを入れ子にしても機能しません。Nesting a template inside a generic won't work either because there's no way to expand the templates at compile time for arbitrary generic types that could be instantiated at runtime.

Example

説明Description

次の例では、テンプレートとジェネリックを一緒に使用する単純な例を示します。The following example shows a simple example of using templates and generics together. この例では、テンプレート クラスがジェネリック型にそのパラメーターを渡します。In this example, the template class passes its parameter through to the generic type. 逆は不可能です。The reverse is not possible.

この方法は、C++/CLI アセンブリにとってローカルなテンプレート コードを既存のジェネリック API 上にビルドするか、ジェネリック型にパラメーター化の層を追加して、ジェネリックではサポートされていないテンプレートの特定の機能を利用する場合に使用できます。This idiom could be used when you want to build on an existing generic API with template code that is local to a C++/CLI assembly, or when you need to add an extra layer of parameterization to a generic type, to take advantage of certain features of templates not supported by generics.

コードCode

// templates_and_generics.cpp
// compile with: /clr
using namespace System;

generic <class ItemType>
ref class MyGeneric {
   ItemType m_item;

public:
   MyGeneric(ItemType item) : m_item(item) {}
   void F() {
      Console::WriteLine("F");
   }
};

template <class T>
public ref class MyRef {
MyGeneric<T>^ ig;

public:
   MyRef(T t) {
      ig = gcnew MyGeneric<T>(t);
      ig->F();
    }
};

int main() {
   // instantiate the template
   MyRef<int>^ mref = gcnew MyRef<int>(11);
}
F

関連項目See also

ジェネリックGenerics