声明typename
参数时,前缀关键字class和typename可以互换。
使用关键字typename标识嵌套从属类型名称,但不需要在基类列表和成员初始化列表内使用。
从属名称:模板内出现的名称,相依于某个模板参数。T t;
嵌套从属名称:从属名称class内呈嵌套状。T::const_iterator ci;
非从属名称:不依赖任何template参数的名称。int a;
如果不特定指出typename,嵌套从属名称,有可能产生解析歧义。
任何时候在模板中涉及一个嵌套从属类型名称,需要在前一个位置,添加关键字typename;
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template<typename T>
void print2nd(const T& container){
typename T::const_iterator iter(container.begin());//不加typename报错
++iter;
int value = *iter;
cout<<value;
}
int main(){
vector<int> vi={1,2,3,4,5};
print2nd(vi);
return 0;
}
例外:嵌套从属类型名称,如果是基类列表和成员初值列中,不使用typename,因为编译器知道这里需要的是类型还是变量。
(1)基类列表里肯定是类型名(2)初始化列表里肯定是成员变量名
#include <iostream>
#include <vector>
using namespace std;
struct Number{
Number(int x){
cout<<"Num="<<x<<endl;
}
};
template<typename T>
struct Base{
typedef Number Nested;
};
template<typename T>
class Derived:public Base<T>::Nested{//不用typename
public :
explicit Derived(int x):Base<T>::Nested(x){//不用typename
typename Base<T>::Nested temp(7);//必须使用
}
};
int main(){
Derived<int> d(5);
return 0;
}