Effective C++条款42:了解typename的双重意义

本文探讨了C++中typename的双重含义,特别是在模板编程中的重要作用。它解释了在声明模板类型参数时,class和typename是等价的,但在处理嵌套依赖类型时,typename是必要的,用于解决解析歧义。文章总结了何时使用typename关键字,以及其在基类列表和成员初始化列表中的限制。
摘要由CSDN通过智能技术生成

考虑以下代码:

template<class T> class Widget;
template<typename T> class Widget;

classtypename有什么不同?
答案:没有不同.当我们声明template类型参数,class和typename的意义完全相同。
然而C++并不总是把class和typename视为等价.有时候一定得使用typename.

假设有以下代码:
有一个函数模板,接受一个STL容器为参数,这个函数仅仅只是打印其第二个元素值.

template<typename C>
void print2nd(const C & container)
{
	if(container.size()>= 2)
	{
		c::const_iterator iter(container.begin());
		++iter;
		int value = *iter;
		std::cout << value;
	}
}

iter的类型是c::const_iterator,实际是什么取决于参数C,模板内出现的名称如果相依于某个模板参数,称之为从属名称.如果从属名称在class内呈嵌套状,我们称它为嵌套从属名称.
c::const_iterator就是一个嵌套从属名称。
value的类型是int,int并不依赖任何模板参数的名称,这样的名称是谓非从属名称.

嵌套从属名称有可能导致解析困难,看下面的例子:

template<typename C>
void print2nd(const C & container)
{
	C::const_iterator *x;
}

看起来好像我们声明x为一个局部变量,它是一个指针,指向一个C::const_iterator.但它之所以被这样认为,是因为我们已经知道C::const_iterator是个类型.如果C::const_iterator不是个类型呢?如果C有个static成员变量而碰巧被命名为const_iterator,或者如果x碰巧是一个全局变量名称呢?

这样的话,上面的代码不再是声明一个局部变量了,而是一个相乘动作:C::const_iterator乘以x.

在我们知道C是什么之前,没有任何办法知道C::const_iterator是否为一个类型.而当编译器开始解析模板print2nd时,尚未知道C是什么东西.

C++有个规则解析这一歧义状态:如果解析器在模板中遭遇一个嵌套从属名称,它便假设这名称不是一个类型,除非你告诉它是.
所以上面的代码不是有效的代码,iter声明式只有在C::const_iterator是个类型时才合理,但我们并没有告诉C++说它是,要想告诉C++说C::const_iterator是个类型,需要在前面加关键字typename:

	typename c::const_iterator iter(container.begin());

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

这个规则的例外是:
typename不可用出现在基类列表内的嵌套从属类型名称之前,也不能在成员初始化列表中作为基类的修饰符.比如:

template<typename T>
class Derived:public Base<T>::Nested //不允许typename
{
public:
	explicit Derived(int x) :Base<T>::Nested(x) //不允许typename
	{
		typename Bast<T>::Nested temp;//需要typename
		...
	}
};

总结:

1.声明template参数时,class和typename可互换.
2.使用关键字typename标识嵌套从属类型名称,但是不能在基类列或成员初始化列表中以它作为基类修饰符

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值