目录
1.1 template 和 template 在模板参数列表中完全一样,可以互换使用。
在 C++ 模板编程中,class
和 typename
在某些情况下可以互换使用,而在某些情况下不能互换,甚至 typename
是必须的。下面是更详细的解释和示例:
1.class
和 typename
可互换
1.1 template<class T>
和 template<typename T>
在模板参数列表中完全一样,可以互换使用。
template<class T> // 合法
void Print1(T value) { cout << value << endl; }
template<typename T> // 也是合法
void Print2(T value) { cout << value << endl; }
int main()
{
Print1(42); // T = int
Print2(3.14); // T = double
}
2.什么时候 class
和 typename
不一样?
2.1 嵌套依赖类型 时必须用typename
虽然 template<class T>
和 template<typename T>
一样,但 typename
在 嵌套依赖类型 时必须用!
必须使用 typename
关键字,以告诉编译器这是一个类型,T
是 模板参数,编译器在解析模板时 并不知道 T::value_type
是类型还是变量。typename
关键字告诉编译器:T::value_type
一定是一个类型。例如:
template <typename T>
class Outer {
public:
using NestedType = typename T::Type; // 必须加 typename
};
如果 T::Type
依赖于模板参数 T
,那么编译器在第一遍解析时无法确定 T::Type
是一个类型还是一个变量。因此,需要显式使用 typename
关键字。
下面是一个完整的代码示例以及代码分析:
template <typename T>
struct Wrapper {
using Type = typename T::value_type; // typename 不能省略
};
struct MyType {
using value_type = int;
};
int main() {
Wrapper<MyType>::Type a = 10; // 正确
return 0;
}
重点说明:
第一步:理解 MyType:MyType
是一个结构体(struct
),using value_type = int;
让 value_type
成为 int
的别名,这意味着 MyType::value_type
等价于 int
。
第二步:理解 Wrapper<T>,
- 这里
Wrapper
是 模板类,T
是一个 模板参数。 using Type = typename T::value_type;
T::value_type
依赖于模板参数T
。typename
不能省略,因为T::value_type
是 依赖类型(编译器在第一遍解析时不确定它是类型还是变量)。Type
变成了T::value_type
的别名。- 如果
T = MyType
,那么展开后等价于:
struct Wrapper<MyType> {
using Type = typename MyType::value_type; // 即 using Type = int;
};
//最终
Wrapper<MyType>::Type == MyType::value_type == int
第三步:main()
函数 :
Wrapper<MyType>::Type
等价于int
。a
的类型就是int
,所以a = 10;
是合法的。
int main() {
Wrapper<MyType>::Type a = 10; // 正确
return 0;
}
2.2 普通作用域(不能互换,不能加 typename
)
在 非模板上下文(普通作用域)中,不允许使用 typename
,也不允许用 class
代替 typename
。
struct MyType {
using value_type = int;
};
int main() {
typename MyType::value_type a = 10; // 错误:非模板作用域不能使用 typename
return 0;
}