web-dev-qa-db-ja.com

テンプレートのキーワード 'typename'と 'class'の違いは?

テンプレートに関しては、私は両方の宣言を見ました:

template < typename T >
template < class T >

違いは何ですか?

そして、これらのキーワードは次の例(テンプレートに関するドイツのウィキペディアの記事から引用)で正確にはどういう意味ですか?

template < template < typename, typename > class Container, typename Type >
class Example
{
     Container< Type, std::allocator < Type > > baz;
};
410
Mat

テンプレートを指定する基本的なケースでは、typenameclassは交換可能です。

template<class T>
class Foo
{
};

そして

template<typename T>
class Foo
{
};

同等です。

そうは言っても、typenameclassの間に違いがある特定のケースがあります。

最初のものは依存型の場合です。この例のtypenameのように、typedefは、別のテンプレートパラメータに依存するネストされた型を参照しているときに宣言するために使用されます。

template<typename param_t>
class Foo
{
    typedef typename param_t::baz sub_t;
};

あなたがそれを理解していないかもしれませんが、あなたが実際にあなたの質問に示す2番目のもの:

template < template < typename, typename > class Container, typename Type >

template templateを指定するときは、classキーワードを上記のように使用しなければなりません - この場合はnottypenameと互換性があります(注) :C++ 17以降、この場合両方のキーワードが許されています)

テンプレートを明示的にインスタンス化するときにもclassを使用する必要があります。

template class Foo<int>;

私が見逃した他のケースがあると私は確信しています、しかし、肝心な点は次のとおりです。

357
Aaron Klotz

テンプレートパラメータの命名では、typenameclassは同等です。 §14.1.2:

Template-parameterのclassとtypenameの間に意味的な違いはありません。

typenameは、テンプレートを使用するときに別のコンテキストで使用可能です - 依存型を参照していることをコンパイラに示唆します。 §14.6.2:

テンプレートの宣言または定義で使用され、template-parameterに依存する名前は、該当する名前の検索でタイプ名が見つからないか、またはキーワードtypenameで修飾されていない限り、タイプの名前を付けないと見なされます。

例:

typename some_template<T>::some_type

typenameがないと、コンパイラは一般的に型を参照しているかどうかを判断できません。

75
Georg Fritzsche

技術的な違いはありませんが、2つはわずかに異なるものを示すために使用されています。

組み込み型(配列など)を含む、Tとして任意の型を受け入れる必要があるテンプレートの場合

template<typename T>
class Foo { ... }

Tが本当のクラスであるところでだけ働くテンプレートのために。

template<class T>
class Foo { ... }

しかし、これは純粋に一部の人々が使用するスタイルのものであることを覚えておいてください。規格で義務付けられていない、またはコンパイラによって強制されていない

18
  1. 変わりはない
  2. テンプレート型パラメータContainerは、それ自体が2つの型パラメータを持つテンプレートです。
6

この断片はc ++入門書からのものです。私はこれが間違っていると確信していますが。

各型パラメータの前には、キーワードクラスまたは型名を付ける必要があります。

// error: must precede U with either typename or class
template <typename T, U> T calc(const T&, const U&);

これらのキーワードは同じ意味を持ち、テンプレートパラメータリスト内で互換的に使用できます。テンプレートパラメータリストは両方のキーワードを使用できます。

// ok: no distinction between typename and class in a template parameter list
template <typename T, class U> calc (const T&, const U&);

テンプレート型パラメータを指定するためにclassではなくキーワードtypenameを使用する方が直感的に思えるかもしれません。結局のところ、テンプレート型引数として組み込み(非クラス)型を使うことができます。さらに、typenameは、あとに続く名前がタイプ名であることをより明確に示しています。ただし、テンプレートがすでに広く使用された後でtypenameがC++に追加されました。一部のプログラマーはクラスを独占的に使い続ける

4
K.K