C++ 模板深入进阶
在深入探讨模板之前,建议先回顾一下模板的基本概念和用法。模板不仅仅是类型参数化,它在泛型编程、适配器模式以及仿函数中都有着广泛的应用。
typename 和 class 的区别
在 C++ 模板中,typename 和 class 在声明模板类型参数时是完全等价的,可以互换使用。两者的主要区别在于语义表达和特定场景下的必要性。
1. 模板参数声明中的等价性
template <class T> class A {};
template <typename T> class A {};
以上两种写法效果等同。通常推荐使用 typename,因为它更明确地表示参数可以是任意类型(包括基本类型),而 class 可能会让人误以为参数必须是一个类。
2. 依赖类型名的显式指明
在模板内部,如果引用一个依赖模板参数的嵌套类型(即依赖类型名),必须使用 typename 来消除歧义。
场景分析: 假设我们要实现一个通用的遍历函数,支持任何容器:
template <typename Container>
void Print(const Container& con) {
// 错误:编译器无法确定 const_iterator 是类型还是静态成员变量
Container::const_iterator it = con.begin();
while (it != con.end()) {
cout << *it << " ";
++it;
}
}
编译时会报错:"const_iterator": 类型从属名称的使用必须以'typename'为前缀。
原因解析:
在语法分析阶段,模板尚未实例化。编译器看到 Container::const_iterator 时,无法判断这是访问类内的静态成员变量,还是访问内嵌的类型定义。加上 typename 后,我们明确告诉编译器这里指的是类型。
修正后的代码:
template <typename Container>
void Print(const Container& con) {
typename Container::const_iterator it = con.();
(it != con.()) {
cout << *it << ;
++it;
}
}


