typename 的用法

Usage

typename 主要有两个作用,让我们先来看下参考文档对该关键字的说明:

  1. 在模板声明的模板形参列表中,typename 可用作 class 的代替品,以声明类型模板形参
  2. 在模板的声明或定义内,typename 可用于声明某个待决的有限定名是类型

声明类型模板形参

以下 template 声明中,class 和 typename 用什么不同?

template <class T>
class Qgw;

template <typename T>
class Qgw;

答案:完全一样。文档中说 typename 可以用来替换 class 声明模板参数类型,并没有说在此时有什么不同。

声明嵌套从属名称

在了解这个作用前,我们需要先学习两种名称,从属名称(dependent names)和嵌套从属名称(nested dependent name)。

让我们来看这样一段代码,代码本身并没有实际意义。

// C 接收一个 STL 容器类型
// 这份代码并不正确
template <class C>
void Test(C& container) {
  C w;
  C::iterator iter(container.begin());
}

在上述代码中有两个局部变量 w 和 iter。w 的类型是 C,实际是什么取决于 template 参数 C。模板函数内出现的名称如果依赖于某个 template 参数,则称其为从属名称。如果从属名称在 class 内呈嵌套状,就称为嵌套从属名称,像 iter 的类型为 C::iterator,就是一个嵌套从属名称

嵌套状的理解:假设 C 是一个 template 参数,我们使用 C 内部的东西。在 C 被编译器具现化之前,编译器并不知道它是什么,也就无从得知 C 里面的 iterator 究竟是个类型还是函数又或是其他东西,因此需要我们用 typename 来指出它是一个类型。

嵌套从属名称有可能导致解析困难,先来看个比较极端的例子:

template <class C>
void Test(C& container) {
  C::iterator* x;
}

上述代码声明了一个局部变量 x,它是个指针,指向一个 C::iterator。但它之所以被这么认为,是因为我们已经知道 C::iterator 是个类型。如果 C::iterator 不是个类型呢?如果 C 有个 static 成员变量而又刚好叫 iterator,并且 x 是个全局变量呢?那样的话上述代码不再是声明一个局部变量,而是一个相乘动作。

在我们知道 C 是什么之前,没有任何办法可以知道 C::iterator 是否是一个类型。C++ 有个规则可以解析这一歧义状态:如果解析器在 template 中遇到一个嵌套从属名称,它便假设这名称不是一个类型,除非你明确指出它是一个类型。所以缺省情况下嵌套从属名称不是类型,有两个例外会在下面指出。

我们可以用 typename 来明确指出嵌套从属名称是一个类型,标准中写到 typename 可以用来声明待决的有限定名(嵌套从属名称)是一种类型。于是我们可以这样修改代码:

template <class C>
void Test(C& container) {
  C w;
  typename C::iterator iter(container.begin());
  typename C::iterator* x;
}

一个简单的规则:任何时候当你想在 template 中指涉一个嵌套从属名称,就必须在它的前一个位置放上关键字 typename

在模板的声明或定义内, typename 可在非待决的有限定类型名(非嵌套从属名称)之前使用(C++11 前)。此情况下它没有效果。

例外

typename 不可以出现在 base classes list 内嵌套从属名称之前,也不可以在 member initialization list(成员初始化列表)中作为 base class 修饰符。例如:

temalate <class T>
class Derived : public Base<T>::Nested { // base classes list 中不允许 typename
public:
  Derived (int x)
      : Base<T>::Nested(x) {             // mem.init.list 中不允许 typename
    typename Base<T>::Nested temp;
  }
}
  • 22
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值