C++ 模板深入进阶
typename 和 class 的区别
在 C++ 模板中,typename 和 class 的选择主要涉及代码风格与特定语法的约束。
1.1 模板参数声明中的等价性
在声明模板类型参数时,两者完全等价,可以互换。唯一的区别在于语义暗示:typename 更明确地表示参数可以是任意类型(包括基本类型),而 class 可能让人误以为必须是类类型(实际上并无此约束)。
template <class T>
class A {};
template <typename T>
class A {};
以上两种写法效果等同。
1.2 依赖类型名的显式指明
在模板内部,如果引用一个依赖模板参数的嵌套类型(即依赖类型名),必须使用 typename 前缀来消除歧义。
比如遍历容器时,直接写 Container::const_iterator 会导致编译错误:"const_iterator": 类型从属名称的使用必须以 "typename" 为前缀。
这是因为编译器在进行语法分析时,模板尚未实例化。它无法确定 Container::const_iterator 是访问静态成员变量还是内嵌类型。加上 typename 就是明确告诉编译器:这里指的是类型。
template <typename Container>
void Print(const Container& con) {
// 必须加 typename 告诉编译器这是类型
typename Container::const_iterator it = con.begin();
while (it != con.end()) {
cout << *it << " ";
++it;
}
cout << endl;
}
当然,现代 C++ 中也可以使用 auto 推导来解决这类问题,例如 auto it = con.begin();,但这不能用于模板参数列表的声明。
1.3 结论
- 优先使用
typename:语义更清晰,且在依赖类型名时必须使用。 - 保留
class的场景:若需兼容旧代码或遵循习惯用法,模板参数声明中保留class也无妨。
非类型模板参数
模板参数分为类型形参和非类型形参。非类型形参允许使用常量作为模板参数,在编译期就能确认结果。


