602

重複の可能性:
テンプレートのキーワード 'typename' と 'class' の C++ の違い

関数テンプレートまたはクラス テンプレートを C++ で定義する場合、次のように記述できます。

template <class T> ...

またはこれを書くことができます:

template <typename T> ...

どちらかを優先する正当な理由はありますか?


私は最も人気のある (そして興味深い) 回答を受け入れましたが、本当の回答は「いいえ、どちらかを優先する正当な理由はありません」のようです。

  • これらは同等です (下記を除く)。
  • を常に使用する理由がある人もいますtypename
  • を常に使用する理由がある人もいますclass
  • 両方を使用する理由がある人もいます。
  • どちらを使うか気にしない人もいます。

ただし、テンプレート テンプレートパラメーターの場合、C++17 より前では、class代わりに を使用するtypename必要があったことに注意してください。以下のuser1428839の回答を参照してください。(しかし、この特定のケースは好みの問題ではなく、言語の要件でした。)

4

10 に答える 10

433

スタン・リップマンはこれについてここで話しました。面白いと思いました。

概要class:新しいキーワードの導入を避けるために、Stroustrup はもともとテンプレートで型を指定するために使用されていました。委員会の何人かは、このキーワードの過負荷が混乱を招くことを懸念していました. その後、委員会はtypename構文のあいまいさを解決するために新しいキーワードを導入し、混乱を減らすためにテンプレートの種類を指定するためにも使用できるようにすることを決定しましたが、下位互換性のためにclass、オーバーロードされた意味を維持しました。

于 2008-10-17T17:47:57.013 に答える
319

Scott Myers によると、Effective C++ (第 3 版) の項目 42 (もちろん、これが最終的な答えになるはずです) - 違いは「何もない」ことです。

T が常にクラスであると予想される場合は「class」を使用し、他の型 (int、char* など) が予想される場合は「typename」を使用することをお勧めします。使用上のヒントと考えてください。

于 2008-10-17T17:52:13.447 に答える
157

上記のすべての投稿への追加として、テンプレート テンプレートパラメーターを処理する場合、classキーワードの使用強制されます (C++14 まで) 。

template <template <typename, typename> class Container, typename Type>
class MyContainer: public Container<Type, std::allocator<Type>>
{ /*...*/ };

この例でtypename Containerは、次のようなコンパイラ エラーが生成されます。

error: expected 'class' before 'Container'
于 2012-07-03T12:57:07.270 に答える
50

私はオーバーロードされたキーワードのファンではないので、typename を使用することを好みます (うわーstatic、さまざまなコンテキストに対していくつの異なる意味があるのでしょうか?)。

于 2008-10-17T17:52:29.470 に答える
17

違いがありますclasstypename

しかし、なぜ?

typenameはテンプレート テンプレート引数に対しては違法であるため、一貫性を保つために、次を使用する必要がありますclass

template<template<class> typename MyTemplate, class Bar> class Foo { };    //  :(
template<template<class>    class MyTemplate, class Bar> class Foo { };    //  :)
于 2012-07-23T15:50:24.110 に答える
9

ただの純粋な歴史。スタン・リップマンからの引用

2 つのキーワードの理由は歴史的なものです。元のテンプレート仕様では、Stroustrup は既存のプログラムを破壊する可能性のある新しいキーワードを導入するのではなく、既存の class キーワードを再利用して型パラメーターを指定していました。新しいキーワードが考慮されなかったわけではありません。ただ、混乱の可能性があることを考えると、必要ではないと見なされただけです。ISO-C++ 標準までは、これが型パラメーターを宣言する唯一の方法でした。

ただし、 classではなくtypenameを使用する必要があります。詳細についてはリンクを参照してください。ただし、次のコードについて考えてみてください。

template <class T>
class Demonstration { 
public:
void method() {
   T::A *aObj; // oops ...
};
于 2010-04-01T08:03:22.097 に答える
9

Mike Bへの回答として、テンプレート内で「typename」にはオーバーロードされた意味があるため、「class」を使用することを好みますが、「class」にはありません。このチェックされた整数型の例を見てください:

template <class IntegerType>
class smart_integer {
public: 
    typedef integer_traits<Integer> traits;
    IntegerType operator+=(IntegerType value){
        typedef typename traits::larger_integer_t larger_t;
        larger_t interm = larger_t(myValue) + larger_t(value); 
        if(interm > traits::max() || interm < traits::min())
            throw overflow();
        myValue = IntegerType(interm);
    }
}

larger_integer_tは従属名であるため、パーサーが型であることを認識できるように、その前に「typename」が必要larger_integer_tです。 一方、 classには、そのようなオーバーロードされた意味はありません。

それは…というか、心が怠け者です。私は 'typename' よりも 'class' を入力する頻度の方がはるかに高いので、入力するのははるかに簡単です。または、OO コードを書きすぎている兆候かもしれません。

于 2008-10-17T20:21:02.867 に答える
8

まったく問題ではありませんが、クラスは、T がクラスにしかならないように見せかけますが、もちろんどの型でもかまいません。したがって、typename の方が正確です。一方、ほとんどの人はクラスを使用しているため、一般的にはクラスの方が読みやすいでしょう。

于 2008-10-17T19:26:10.560 に答える
1

私の知る限り、どちらを使用しても問題ありません。コンパイラの目には、それらは同等です。お好きな方を使用してください。私は通常クラスを使用します。

于 2008-10-17T17:47:35.953 に答える
-6

DarenW のコメントを拡張します。

typename と class が大きく異なることが認められなくなったとしても、それらの使用を厳密にすることは依然として有効な場合があります。が本当にクラスである場合にのみ class を使用し、charなどの基本型である場合は typename を使用します。

これらの型は実際にtypenameの代わりに受け入れられます

テンプレート< char myc = '/' >

この場合、これは typename や class よりも優れています。

「ヒント」または他の人にとっての理解度について考えてみてください。そして、実際には、サードパーティのソフトウェア/スクリプトがコード/情報を使用して、テンプレートで何が起こっているかを推測しようとする可能性があることを考慮してください (swig を検討してください)。

于 2009-10-28T12:37:56.870 に答える