条款42:了解typename的双重意义。

在模板的的声明中,class与typename是没有什么区别的:

template <typename T> T func1(const T&);
template <class T> T func2(const T&);

但是在模板的定义中typename有时候却会派上用场。为了说明问题,我们先了解一下两个名词:从属名称和非从属名称。从属名称是依赖于某个类型的,比如迭代器,它是依赖于你的容器类型的;而非从属名称就不依赖其他类型,比如int。有了这两个基本概念之后我们就可以看一下例子了:
假设我们要打印一个容器(里面为)中的第二个元素,那么函数应该是这样:

template <typename C> void print2nd(const C& container)
{
	if(container.size() >= 2)
	{
		C::const_iterator iter(container.begin());
		++iter;
		std::cout<<*iter;
	}
}
其中的C::const_iterator,就依赖与传进去的容器的类型。虽然对于这个例子可以成功,但是还是要强调,对于从属名称(这里是C::const_iterator)最好在前面加上typename ,这样可以确保编译器将它看做一个类型名而不是其他什么的。举一个例子,如果是定义为一个指向迭代器的指针:

	if(container.size() >= 2)
	{
		
		typename C::const_iterator iter(container.begin());
		typename C::const_iterator* pIter = &iter;
		++(*pIter);
		std::cout<<*(*pIter)<<endl;
	}
如果却掉typename 就不行了,为什么呢?因为编译器总是会假设你遇到的不是一个类型就会把指针类型*当做乘号,然后就错了。
但是总有例外:typename不能出现在基类列表的嵌套从属类型之前,也不可出现在成员初始化列表中作为类型的限定符。
最后,为了获得迭代器所指的类型,可以通过typename std::iterator_traits<C::const_iterator>::value_type temp(*iter);来实现;而且最好是使用typedef来简化代码:

		typedef typename std::iterator_traits<C::const_iterator>::value_type type;
		type tmp = (*iter);

总之,当声明模板参数时,typename与class可以互换,而在模板中定义从属名称时,则只能使用typename,但是在基类列表和成员初始哈列表中,不能使用typename来指明从属名称。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值