文章目录
从属类型、嵌套从属类型和非从属类型——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修饰符。