回答:
typename
そしてclass
、テンプレートを指定する基本的なケースでは交換可能です:
template<class T>
class Foo
{
};
そして
template<typename T>
class Foo
{
};
同等です。
それを言っても、違いがあり、特定の例があるtypename
とはclass
。
1つ目は、依存型の場合です。次の例のtypename
ように、別のテンプレートパラメータに依存するネストされた型をいつ参照するかを宣言するために使用されますtypedef
。
template<typename param_t>
class Foo
{
typedef typename param_t::baz sub_t;
};
あなたがそれをあなたが実際にあなたの質問で示す2番目のもの、あなたはそれを理解していないかもしれませんが:
template < template < typename, typename > class Container, typename Type >
テンプレートテンプレートを指定するときは、class
キーワードを上記のように使用する必要があります。この場合、キーワードは交換できません(注:typename
この場合、C ++ 17では両方のキーワードを使用できるため)。
class
テンプレートを明示的にインスタンス化するときにも使用する必要があります。
template class Foo<int>;
私が見逃した他のケースがあると確信していますが、肝心なのは、これらの2つのキーワードは同等ではなく、これらはどちらか一方を使用する必要があるいくつかの一般的なケースです。
std::vector<int>::value_type
依存タイプは、あなたが必要としないではないtypename
タイプは、テンプレートパラメータに依存している場合、あなただけ言う、それを必要とする-がtemplate<class T> struct C { typedef typename std::vector<T>::value_type type; };
param_t
、依存型ではありません。依存タイプには、テンプレートパラメータに依存する名前、たとえばfoo<param_t>::some_type
、いないテンプレートパラメータそのもの。
GCC 5
、G ++はテンプレートテンプレートパラメータでtypenameを許可しています。
テンプレートパラメータの命名用でtypename
、class
同等です。§14.1.2:
テンプレートパラメータのクラスとタイプ名の間に意味上の違いはありません。
typename
ただし、テンプレートを使用する場合、別のコンテキストでは、依存型を参照していることをコンパイラに示唆することができます。§14.6.2:
テンプレートの宣言または定義で使用され、template-parameterに依存する名前は、適切な名前の検索でタイプ名が見つからないか、名前がキーワードtypenameで修飾されていない限り、タイプに名前を付けないと見なされます。
例:
typename some_template<T>::some_type
なければtypename
、コンパイラあなたがタイプに言及されているかどうか、一般的に言うことはできません。
技術的な違いはありませんが、2つは少し異なることを表すために使用されているのを見てきました。
組み込み(配列など)を含むTとして任意の型を受け入れる必要があるテンプレートの場合
template<typename T>
class Foo { ... }
Tが実際のクラスでのみ機能するテンプレートの場合。
template<class T>
class Foo { ... }
ただし、これは純粋に一部の人々が使用するスタイルであることを覚えておいてください。標準によって義務付けられていないか、コンパイラによって強制されていません
T t; int i = t.toInt();
)、あなたは「本当のクラス」を必要とし、あなたが提供する場合は、あなたのコードがコンパイルされませんint
のためにT
...
class
おそらく、いくつかの演算子をサポートする「値」を期待しているのではなく、構築や割り当てをコピーまたは移動するだけでなく、メンバーアクセスのセマンティクスをサポートする型が特に必要であることを意味します。宣言を一目見ただけで、期待と落胆class
が明らかになります。たとえば、間違いである場合は、パラメーターに組み込み型を指定することになります。
Container
自体は、2つの型パラメーターを持つテンプレートです。
template<template<class U> class V> struct C {};
この抜粋は、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&);
テンプレートタイプパラメータを指定するために、クラスではなくキーワードタイプ名を使用する方が直感的に見えるかもしれません。結局のところ、組み込み(非クラス)型をテンプレートの型引数として使用できます。さらに、typenameは、後に続く名前がタイプ名であることをより明確に示します。ただし、typenameは、テンプレートがすでに広く使用されていた後にC ++に追加されました。一部のプログラマーはクラスを排他的に使用し続けます
template <typename T> typename Foo {};
Foo <T>は間違いなくクラスであるため、コードの最初の2ビットはで置き換えることができません。