typename
在template的声明式中
- template< class T>//声明方法1
- template< typename T>声明方法2,使用typename 可以暗示参数不一定是一个class类型
使用方法1和方法2意义完全相同。但是涉及嵌套从属名称时只能使用关键字typename:
template<typename C>
void print1st(const C& container)
{
if(container.size()>)
{
C::const_iterator iter(container.begin());//局部变量iter是从属名称
int value = * iter;//局部变量value是非从属名称
std::cout<<value;
}
}
从属名称(dependent name):template内出现的名称(示例中的iter)如果相依于某个template参数(示例中的C)的名称。如果从属名称在class内呈嵌套状,则称为嵌套从属名称(nested dependent name)。const_iterator也是类。
非从属名称(non-dependent name):不依赖于任何template参数的名称。
嵌套从属名称可能导致解析困难:
template<typename C>
void print1st(const C& container)
{
C::const_iterator* x;//如果const_iterator是类,则x是一个指向const_iterator的指针,但如果const_iterator是一个变量的名称,则是一个相乘动作。
}
C++中一个相关的解析规则:如果解析器在template中遭遇一个嵌套从属名称,便假设这名称不是一个类型,除非你通过放置关键字typename告诉它是
template<typename C>
void print1st(const C& container)
{
typename C::const_iterator* x;//通过放置关键字typename说明const_iterator是类
}
也就是说:任何时候当你想要在template中指涉一个嵌套从属类型名称,就必须在紧邻它的前一个位置放置typename关键字作为前缀词。这个规则的例外:
- 不可以出现在base classes list内的嵌套从属名称之前
- 不可以出现在member initialization list(成员初值列)中作为base class修饰符
template<typename T>
class derived:public base<T>::nested{//此处不可以
public:
explivit derived(int x):base<T>::nested(x){//此处不可以
typename base<T>::nested temp;//此处可以
}
}