天天看点

Effective C++第七章-模板和泛型编程之typename与嵌套从属名称

typename

在template的声明式中

  1. template< class T>//声明方法1
  2. 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关键字作为前缀词。这个规则的例外:

  1. 不可以出现在base classes list内的嵌套从属名称之前
  2. 不可以出现在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;//此处可以
    }
}
           

继续阅读