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


504

テンプレートについては、両方の宣言を見てきました。

template < typename T >
template < class T >

違いは何ですか?

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

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

回答:


430

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つのキーワードは同等ではなく、これらはどちらか一方を使用する必要があるいくつかの一般的なケースです。


45
最後の1つは、クラスを定義するためにtypenameではなく、classまたはstructを使用する必要があるという事実のかなり特殊なケースです。template <typename T> typename Foo {};Foo <T>は間違いなくクラスであるため、コードの最初の2ビットはで置き換えることができません。
Steve Jessop

2
std::vector<int>::value_type依存タイプは、あなたが必要としないではないtypenameタイプは、テンプレートパラメータに依存している場合、あなただけ言う、それを必要とする-がtemplate<class T> struct C { typedef typename std::vector<T>::value_type type; };
ゲオルクフリッチェ

2
またparam_t、依存型ではありません。依存タイプには、テンプレートパラメータに依存する名前、たとえばfoo<param_t>::some_type、いないテンプレートパラメータそのもの。
Georg Fritzsche、2010年

2
A C ++ 1Z提案N4051は、あなたが使用できるようになりますtypenameすなわち、template <typename> typename C
user4112979 2014年

4
現在GCC 5G ++はテンプレートテンプレートパラメータでtypenameを許可しています
Chnossos 2014年

95

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

テンプレートパラメータのクラスとタイプ名の間に意味上の違いはありません。

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

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

例:

typename some_template<T>::some_type

なければtypename、コンパイラあなたがタイプに言及されているかどうか、一般的に言うことはできません。


2
ルールは理解していますが、コンパイラがsome_template <T>を内部で型として処理するのを正確に妨げているのはなぜですか 明らかなものがない場合は申し訳ありません。
batbrat

23

技術的な違いはありませんが、2つは少し異なることを表すために使用されているのを見てきました。

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

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

Tが実際のクラスでのみ機能するテンプレートの場合。

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

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


15
言及したことであなたを責めることはありませんが、プログラマーは重要ではないこと(「私は正しいものを使用したか?」)を考えるのに時間を費やしてしまうので、このポリシーはかなり見当違いだと思います問題(「このテンプレートパラメータに必要なインターフェースを実装する組み込み型が存在しますか?」)テンプレートパラメータのいずれかのメンバーが使用されている場合は(T t; int i = t.toInt();)、あなたは「本当のクラス」を必要とし、あなたが提供する場合は、あなたのコードがコンパイルされませんintのためにT...
スティーブ・ジェソップ

1
使用を実際のクラスに限定したい場合は、クラス以外のタイプのエラーをスロー/発生させる特殊化を追加することをお勧めします。使用を特定のクラスに限定したい場合は、それらに特化してください。いずれにせよ、そのような文体の違いは微妙すぎてメッセージを伝えることができません。
Potatoswatter 2010年

2
同じ意味なので、1つだけ使ってください。それ以外の場合は、火曜日でない限り、インライン{を使用するようなものであり、次の行{を使用します。
Paul Draper

+1自分でこれを行うこともあります... classおそらく、いくつかの演算子をサポートする「値」を期待しているのではなく、構築や割り当てをコピーまたは移動するだけでなく、メンバーアクセスのセマンティクスをサポートする型が特に必要であることを意味します。宣言を一目見ただけで、期待と落胆classが明らかになります。たとえば、間違いである場合は、パラメーターに組み込み型を指定することになります。
Tony Delroy、2015

テンプレートがどのクラスでも機能するが、組み込み型では機能しない実際の状況にはどのようなものが存在するのかを理解したいと思います。例はありますか?
lfalin 2015年

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

3
一般的に違いがあります。
Hassan Syed

コンテナーがテンプレート化されているこれらの2つのパラメーターにも名前を付けることができますか?この例では、名前はありません。また、この例では「クラスコンテナ」と記述されていますが、代わりに「タイプ名コンテナ」と記述することもできますか?
マット

2
@マット:はい、検索する用語はテンプレートテンプレートパラメータ/引数です。例:template<template<class U> class V> struct C {};
Georg Fritzsche、2010年

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&);

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.