typename和class在模板声明和定义上没有区别,下面的两段代码在功能上一样:
template <typename T>
const T& max(const T& x, const T& y) {
return x > y ? x : y;
}
template <class T>
const T& max(const T& x, const T& y) {
return x > y ? x : y;
}
但如果遇到下面这种情况:
template <class T>
void foo(const T& t) {
T::bar *p;
/*意图:定义一个模板中的bar类型的指针
* 但此处编译器无法区分bar是类型名还是变量名
* 为消除歧义,C++默认此处为变量名,则p就是一个未声明的变量
* 此处的*编译器理解为乘号
* 所以小伙伴们要是这么用的话就会报
* ‘p’ was not declared in this scope
*/
}
struct Bar {
typedef int bar;
};
int main() {
Bar x;
foo(x);
return 0;
}
那C++提出的解决方案是采用typename作为类型名指示符,显示告诉编译器这里是要用类型名而不是变量名:
template <class T>
void foo(const T& t) {
typename T::bar *p; //定义一个模板中bar类型的指针
}
当在初始化列表中或者被继承的基类列表中无需使用typename,因为初始化列表中一定是变量,被继承的基类列表中一定是类型,此处编译器是可以区分的。