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

从属类型、嵌套从属类型和非从属类型——234

我们来看下面例子:

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,实际是什么必须取决于template参数C。template内出现的名称如果相依于某个template参数,称之为从属名称。如果从属名称在classs内呈嵌套状,我们称它为乔涛从属名称。int是一个并不依赖任何template参数的名称。这样的名称是谓非从属名称。

无论何时,请在嵌套从属类型名称前放上关键字typename——234

我们在改写上节代码:

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

上面的iter类型解析很困难,因为如果C不是一个类型名,或者C有个static成员变量碰巧被命名为const_iterator,又或者x碰巧是个global变量名称,则上述代码不再是声明一个local变量,而是一个相乘动作。
为了解决这个问题,我们在C::const_iterator名称前加上typename即可:

template<typename C>
void print2nd(cosnt C& container)
{
    f(container.size()>=2){
        typename C::const_iterator iter(container.begin());      //ok
        ...
    }
}

typename 不可出现在base class list内的嵌套从属类型名称之前,也不可在member initializationlist中作为base class 修饰符——236

直接看例子:

template<typename T>
class Derived:public Base<T>::Nested{   //base class list中不允许“typename”
public:
    explicit Derived(int x):Base<T>::Nested(x)  //mem.init.list中不允许“typename”
    {
        typename Base<T>::Nested temp;      //嵌套从属类型名称前需要加typename
        ...
    }
    ...
};

总结——237

(1)声明template参数时,前缀关键字class和typename可互换。
(2)请使用关键字typename标识嵌套从属类型名称:但不得在base class list(基类列)或member initialization(成员初值列)内以它作为base class修饰符。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值