C++ typename的双重含义

版权声明:感谢您对博文的关注!校招与社招,有需要内推腾讯的可以QQ(1589276509)or 微信(louislvlv)联系我哈,期待您的加入。 https://blog.csdn.net/K346K346/article/details/82751245

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的。

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

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的双重意义
[2]陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008[6.9 typename的用法]

猜你喜欢

转载自blog.csdn.net/K346K346/article/details/82751245