Skip to the content.

cpp template : typename class

typename 和 class 要分场景看:声明模板类型参数时可以互换;显式标明依赖名称是类型时用 typename。

声明模板类型参数:两者等价

下面两种写法含义完全相同,选择其中一种即可:

template <typename T>
void foo(T value) {}
template <class T>
void foo(T value) {}

这里的 class 不代表 T 必须是类,它也可以是 int、指针等类型:

foo<int>(42);
foo<double>(3.14);

两种写法也都能用于类模板,下面同样选择其中一种即可:

template <typename T>
class Box {};
template <class T>
class Box {};

实际代码里,选择一种风格并保持一致即可。不要把上述两种等价定义同时放进同一作用域,否则会造成重定义。

标明依赖于模板参数的类型:用 typename

考虑下面的代码:

template <typename T>
void foo()
{
    typename T::value_type x{};
}

T::value_type 的含义取决于模板参数 T,因此称为依赖名称。在模板定义阶段,编译器无法直接确定它是类型,还是静态数据成员等其他东西。

这里的 typename 告诉编译器:把 T::value_type 当作类型来解析。

例如:

struct MyType {
    using value_type = int;
};

// 在函数中调用:
foo<MyType>();  // x 的类型是 int

这种用途不能换成 class:

typename T::value_type x{};  // 正确
class T::value_type x{};     // 不能作为等价替换

常见例子是容器的迭代器类型:

template <typename Container>
void traverse(const Container& c)
{
    typename Container::const_iterator it = c.begin();
}

如果使用 auto,就不用写出该类型:

auto it = c.begin();

注意,并非所有依赖类型出现的位置都必须写 typename;部分语法位置本来就被视为类型,C++20 也进一步放宽了规则。

声明普通类:用 class

class Foo;      // 类的前向声明
class Bar {};   // 类的定义

这里不能用 typename 替换。

对照表

场景 typename class
模板类型参数:template <... T> 可以 可以,含义相同
显式标明依赖名称是类型:... T::value_type 使用它 不能等价替换
普通类的声明或定义 不可以 使用它

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。