2010-06-12
あるテンプレート関数(テンプレート型引数 T)で,例えば std::vector<T>::iterator itr を定義しようとすると,コンパイルエラーとなる(std::vector<T>::iterator が型であると認識されない).この場合 typename std::vector<T>::iterator itr のように,前に typename をつけて,型であることを明示する.もし,iterator に相当するものが,テンプレートクラスの場合,template キーワードを使ってテンプレートであることを明示しなければならない.
例えば,
template <typename T1>
struct TTest
{
struct TIn
{
double X;
};
};
こんな構造体があったとして,
template <typename T1>
void Func (void)
{
TTest<T1>::TIn test;
test.X= 1.2;
cout<<"test.X= "<<test.X<<endl;
}
のような感じで TTest::TIn のインスタンスを生成したいとする.これはコンパイルエラーとなる.g++ の場合(51行目が当該箇所),
tmpl-in-struct.cpp: In function 'void Func()': tmpl-in-struct.cpp:51: error: expected ';' before 'test' tmpl-in-struct.cpp:52: error: 'test' was not declared in this scope tmpl-in-struct.cpp: In function 'void Func() [with T1 = int]': tmpl-in-struct.cpp:58: instantiated from here tmpl-in-struct.cpp:51: error: dependent-name 'TTest::TIn' is parsed as a non-type, but instantiation yields a type tmpl-in-struct.cpp:51: note: say 'typename TTest::TIn' if a type is meant
のようなエラーを吐く.よく読めば,typename を使えばいいと分かる.つまり,
typename TTest<T1>::TIn test;
とすればよい.これでコンパイルが通る.
次に,TIn もテンプレートの場合:
template <typename T1>
struct TTest
{
template <typename T2>
struct TIn
{
T2 X;
};
};
この場合,
template <typename T1, typename T2>
void Func (void)
{
typename TTest<T1>::TIn<T2> test;
test.X= 1.2;
cout<<"test.X= "<<test.X<<endl;
}
とするだけだと,コンパイルエラーとなる.g++ の場合(26行目が当該箇所),
tmpl-in-struct.cpp:26: error: non-template 'TIn' used as template tmpl-in-struct.cpp:26: note: use 'TTest<T1>::template TIn' to indicate that it is a template tmpl-in-struct.cpp:26: error: declaration does not declare anything tmpl-in-struct.cpp:27: error: 'test' was not declared in this scope
のようなエラーを吐く.TTest<T1>::TIn がテンプレートと認識されていないようだ.認識させるためには,エラーに書いてあるように,template キーワードを使って,
typename TTest<T1>::template TIn<T2> test;
とすればよいらしい.この template キーワードの使い方は今日初めて知った.