首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++ typename的双重含义

C++ typename的双重含义

作者头像
恋喵大鲤鱼
发布2018-09-27 16:04:31
1.2K0
发布2018-09-27 16:04:31
举报
文章被收录于专栏:C/C++基础C/C++基础

1.模板类型参数申明

使用模板时,在申明模板类型参数时,我们经常有如下两种申明方式:

//方式一
template <class T> CTest;

//方式二
template <typename T> CTest;

这两种写法并没有任何区别,都是标记T是模板类型参数,可以是任何类型,包括用户自定义类型或是语言的基本类型。虽然而这在用于模板类型参数申明时的作用完全相同,但是仍建议使用typename,因为typename的字面意义即表示类型名称,更加符合其语义。而class则多用于类的申明,而非模板类型参数。当然,如果原有项目中均使用class,那么请与原有项目风格保持一致。

2.嵌套从属类型名称(nested dependent type name)须使用typename

在template声明式中,用于申明模板类型参数时,class与typename作用完全一致。当然,因为前者字符数少,可能会有人倾向于使用class。但有些时候,typename却是不可被替换成class的。

假设,有个template function,接受了一个容器C为参数,这个容器内部定义了一个类型a,如果了解STL,想必会知道容器内部会定义5种迭代器型别(iterator_category, value_type, difference_type, pointer, reference),这里a可以是其中任何一个,也可是用户自定义类型,但假设不是基本类型。现在看这个template function的定义:

template<typename C>			//建议使用typename
void func(const C& container) 
{
	//...
    C::a* x;
	//...
}

考虑上面模板定义式中间那行代码,对于开发者而言,可以很明显的推断出代码的含义,x是一个a类型的指针。但是对于编译器而言,在没有明确C的定义之前,是无法确定a是一个嵌套于C中的类型,其实a可能是C内一个静态成员变量,假设x刚好是一个全局变量,那么这行代码也可以由编译器解析为两数相乘。

编译器面对这样的代码如何处置?编译器会这样处理:如果在template中遇到一个嵌套从属类型名称,即依赖于模板类型参数的类型,放在上面例子中对应C::a,C::a依赖于模板类型参数C,它便假设这个名称不是个类型,除非显示告诉编译器。所以缺省情况下嵌套从属类型名称不是类型。如何显示告知呢,可以使用typename,这是它的第二重意义。在此对之前假设a不是基本类型,因为基本类型并不依赖其它类型。

正确的函数模板定义如下:

template<typename C>
void func(const C& container) 
{
	//...
	typename C::a * x;	//在行首加上typename即可
	//...
}

到这里,想必对typename的第二重含义已经基本了解,这也是typename与class的不同之处,模板中当出现嵌套从属类型名称时须使用typename帮助编译识别。

3.规则之外

模板中当出现嵌套从属类型名称时须使用typename帮助编译识别,这一规则也存在例外。typename不可以出现在base classes list(所继承的基类成员列表)内的嵌套从属类型名称之前,也不可以在member initialization list(成员初始化列表)中作为base class修饰符。例如:

template<typename T>
class Derived: public Base<T>::Nested 			//基类成员列表中不允许使用typename
{ 
public:
    explicit Drived(int x) : Base<T>::Nexted(x) 	//成员初始化列表中不允许使用typename
    {
        typename Base<T>:: Nexted temp;	//这里可以
    }

4.小结

(1)申明模板参数时,class和typename可以互换,建议使用typename,因为从字面更加符合语义; (2)嵌套从属类型名称(nested dependent type name)须使用typename来标识,但不能在所继承的基类成员列表和成员初始化列表中使用。


参考文献

[1]Effective C++:改善程序与设计的55个具体做法(第3版 中文版)[M].条款四十二:了解typename的双重意义

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年09月18日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.模板类型参数申明
  • 2.嵌套从属类型名称(nested dependent type name)须使用typename
  • 3.规则之外
  • 4.小结
  • 参考文献
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档