C++で関数テンプレートやクラステンプレートを定義するとき、これを書くことができます。
template <class T> ...
または、これを書くことができます:
template <typename T> ...
一方を他方よりも優先させる正当な理由はありますか?
私は最も人気のある(そしておもしろい)答えを受け入れました、しかし本当の答えは「いいえ、一方を他方よりも好む理由はありません」のようです。
typename
を常に使う理由があります。class
を常に使う理由があります。ただし、テンプレートテンプレートパラメータの場合は、class
の代わりにtypename
を使用する必要があります。下記の user1428839の回答 を参照してください。 (ただし、この特定のケースは好みの問題ではなく、言語の要件です。)(これもc++17
によって変わります)
スタンリップマンはこれについて話しました こちら 。面白いと思いました。
Summary:Stroustrupは、元々class
を使用してテンプレートにタイプを指定し、新しいキーワードの導入を避けました。委員会の何人かは、このキーワードの過負荷が混乱を招くことを心配した。その後、委員会は新しいキーワードtypename
を導入して、構文のあいまいさを解決し、混乱を減らすためにテンプレートタイプの指定にも使用することを決定しましたが、下位互換性のために、class
はそのオーバーロードされた意味を維持しました。
Scott Myersによると、Effective C++(3rd ed。)item 42(もちろん、これは究極の答えであるに違いない) - 違いは「何もない」。
Tが常にクラスになることが予想される場合は "class"を使用し、他のタイプ(int、char *その他)が予想される場合は "typename"を使用することをお勧めします。使い方のヒントと考えてください。
上記の記事すべてに加えて、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'
私は、オーバーロードされたキーワードのファンではないので、typenameを使用することを好みます(jeez - static
は、さまざまなコンテキストに対していくつの異なる意味を持ちますか?)。
class
よりtypename
を選ぶべきです。typename
はテンプレートテンプレートの引数には無効です。そのため、一貫性を保つためにclass
を使用する必要があります。
template<template<class> typename MyTemplate, class Bar> class Foo { }; // :(
template<template<class> class MyTemplate, class Bar> class Foo { }; // :)
Mike B に応答して、テンプレート内では 'typename'はオーバーロードされた意味を持ちますが、 '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
は従属名なので、パーサーがlarger_integer_t
が型であることを認識できるようにするには、 'typename'を先に付ける必要があります。一方、classはそのようなオーバーロードされた意味を持ちません。
それは……あるいは私はただ怠け者です。私は 'typename'よりはるかに頻繁に 'class'をタイプします、そしてそれ故にそれがタイプすることがはるかに簡単であるとわかります。あるいは、私がOOコードを書きすぎたというサインかもしれません。
純粋な歴史です。 Stan Lippmanからの引用 :
2つのキーワードの理由は歴史的なものです。元のテンプレート仕様では、Stroustrupは既存のプログラムを壊す可能性のある新しいキーワードを導入するのではなく、既存のクラスキーワードを再利用して型パラメータを指定しました。新しいキーワードが考慮されなかったというわけではありません - それがその潜在的な混乱を考えると必要であると考えられなかったということだけです。そしてISO-C++標準までは、これが型パラメータを宣言する唯一の方法でした。
しかし、classではなくtypenameを使うべきです。詳細についてはリンクを参照してくださいが、次のコードについて考えてください。
template <class T>
class Demonstration {
public:
void method() {
T::A *aObj; // oops ...
};
それはまったく問題ではありませんが、classはTがクラスにしかなれないように見えますが、もちろんどんな型でもかまいません。だからtypenameはもっと正確です。一方、ほとんどの人はクラスを使用しているので、一般的に読みやすくなっています。
私の知る限りでは、どちらを使用してもかまいません。これらはコンパイラから見ると同等です。好きな方を使用してください。私は通常クラスを使います。