業務でつまづいたことメモ。
テンプレートパラメータの宣言でclassとtypenameの違いはないが、typenameにはもう一つの意味があって、これを使わなければならない場所がある。例えば、STLコンテナを引数に取る関数テンプレートを作る時、
[cpp]
template
void func(const T& container) {
if(container.size() > 2) {
T::const_iterator iter(container.begin()); // 型名とは解釈されないのでエラー
…
[/cpp]
C++には、テンプレート内にあるネストされた依存名は、特に指示されていなければ型名とは解釈されないというルールがある。T::const_iteratorを型名と解釈させるためにはコンパイラに指示を与える必要があるが、ここで使うのがtypename。
[cpp]
template
void func(const T& container) {
if(container.size() > 2) {
typename T::const_iterator iter(container.begin()); // 依存型名の頭にtypenameを付ける
…
[/cpp]
typenameはネストされた依存名でのみ使う。
[cpp]
template
void f(const C& container, // typenameは使えない
typename C::iterator iter); // typenameが必要
[/cpp]
ただし、派生クラスを定義するときの基底クラスの指定と、初期化子リスト内での基底クラスの指定ではtypenameは使わないので注意。
[cpp]
template
class Derived:public Base
public:
explicit Derived(int x) // 初期化子リスト内での基底クラスの指定ではtypenameを使えない
:Base
{
typename Base
…
}
…
};
[/cpp]
参考:Effective C++ 42項