使用场景
typename使用场景有两种:
(1) 在定义模板类或者模板函数时,我可以可以用typename来替换class。
(2) 当编译器不能明显知道某个标识符是类型的时候
测试代码
测试一
template <typename T>
struct MyClass
{
typedef double Y; // Y may or may not be a type
typedef T Type; // Type is always a type
};
template < >
struct MyClass<int>
{
static const int Y = 314; // Y may or may not be a type
typedef int Type; // Type is always a type
};
template <typename T>
auto SomeFunc()
{
MyClass<T>::Y a;
return a;
};
int main()
{
SomeFunc<char>();
return 0;
}
分析和结论
运行上面的代码我们发现会编译不过,原因是模板函数SomeFunc 使用了 模板类MyClass,且MyClass的类型参数是不确定的T,但形如 MyClass::Y不一定是一个类型,也可以是类中的static变量。在SomeFunc中我们显然是希望 MyClass::Y是一个类型的,所以我们需要加上typename告诉编译器,这是一个类型。
测试二
现在我们加上typename
分析和结论
这时我们发现编译通过了
测试三
这时我们再观察下代码,我们还发现我们为MyClass做了偏特化,所有int的Y都是成员变量,而其他类型的Y则为类型。
那如果我们明确MyClass的参数为非int呢?
结果和结论
我们发现编译通过,这里直接匹配了非int的偏特化的版本,不需要加typename告诉编译器
总结
如果某个模板类的传入类型参数是确定的,则不必加typename修饰类型
如果模板类传入类型是模糊的,则需要加typename修饰类型,因为可能某个偏特化版本中是static变量