C++模板中的typename

一、class 和 typename

如下例所示:

1
2
3
4
5
6
// 以下两种写法完全等价
template <typename T>
void func(T t) {}

template <class T>
void func(T t) {}

历史原因:class 是 C++98 引入模板时的关键字,typename 是后来加入的。现在更推荐使用 typename,因为它更准确地表达了”类型参数”的含义(不一定非得是类)。

唯一例外 :模板模板参数中只能用 class(C++17 后也可以用 typename

1
2
3
4
5
6
7
// 模板模板参数(老语法只能用 class)
template <template <typename> class Container>
struct MyClass {};

// C++17 开始也可以写 typename
template <template <typename> typename Container>
struct MyClass {}; // C++17

二、typename 的用途

见下例:

1
2
3
4
5
6
template <typename T>
void printSize(const T& container) {
// T::size_type 是什么?是一个类型,还是一个静态成员变量?
T::size_type size = container.size(); // 编译错误
cout << size << endl;
}

编译器在解析 T::size_type 的时候,不知道 T 是什么,因为模板参数直到实例化的时候才能确定。按照 C++ 规则,如果编译器不能确定一个名称是类型,它就认为不是类型(默认当作成员变量或静态函数)。

解决方案:用 typename 明确告诉编译器“这是一个类型”。

1
2
3
4
5
6
7
8
template <typename T>
void printSize(const T& container) {
typename T::size_type size = container.size(); // 正确
cout << size << endl;
}

vector<int> v = {1, 2, 3};
printSize(v); // T = vector<int>, T::size_type = size_t

三、消除模板成员调用歧义

类似 typename 的歧义也发生在调用模板成员函数时。见下例:

1
2
3
4
5
6
template <typename T>
void process(T& obj) {
// obj.templateMethod<int>() 是什么意思?
// 编译器不知道 templateMethod 是模板函数还是成员变量
obj.templateMethod<int>(); // 如果不加 template,编译错误
}

编译器看到 <>,可能认为这是小于号和大于号,而不是模板参数列表。

解决方案 :用 .template 明确告诉编译器。

1
2
3
4
5
6
7
8
9
template <typename T>
void process(T& obj) {
// .template 告诉编译器:后面是一个模板成员函数
obj.template templateMethod<int>();

// 同样适用于指针:->template
T* ptr = &obj;
ptr->template templateMethod<double>();
}

总结:

语法 用途 示例
typename 声明从属类型名称 typename T::iterator
.template 调用模板成员函数 obj.template func()
->template 通过指针调用模板成员函数 ptr->template func()
::template 通过作用域运算符调用 T::template func()

四、标准库中的应用

std::allocator_traits

1
2
3
4
5
6
7
8
9
template <typename T>
struct allocator_traits {
// 需要 typename:pointer 是从属类型
using pointer = typename T::pointer;

// 需要 .template:rebind 是模板成员
template <typename U>
using rebind = typename T::template rebind<U>;
};

std::iterator_traits

1
2
3
4
5
6
7
template <typename Iter>
struct iterator_traits {
using iterator_category = typename Iter::iterator_category;
using value_type = typename Iter::value_type;
using difference_type = typename Iter::difference_type;
// ...
};

C++模板中的typename
http://example.com/2026/04/16/C++-模板中的typename/
作者
Yu xin
发布于
2026年4月16日
许可协议