typeneme的双重意义!

来源:互联网 发布:电信有哪些软件 编辑:程序博客网 时间:2024/05/18 03:25

typeneme的双重意义!

—–effective c++ item42.


typename和class在template声明式中,并没有什么不同.

template<class T> class Foo;template<typename T> class Goo;

从c++角度看,声明template时,不论使用关键字class或者typename,他们的意义完全相同.


嵌套从属类型名称

template 内出现的名称如果相依于某个template参数,就称它为从属名称(dependent names). 如果从属名称在class 内成嵌套状,它就是嵌套从属名称(nested dependent name).

并不好理解….还是先考虑下面的代码.

// 错误的代码..不能通过编译// print_2nd接受stl容器为参数,并打印第二个元素的值.template<typename T>void print_2nd(const T &container)      // 接受stl容器为参数{    if(container.size() >= 2) {        T::const_iterator iter(container.begin());      // iter的类型取决于T的类型,因此iter是从属名称.        iter++;        int value = *iter;        std::cout << value << std::endl;    }}

上面的代码中,iter实际上是一个嵌套从属类型名称.而它的类型T::const_iterator则是嵌套从属类型名称(nested dependent type name),也就是个嵌套从属名称并且指向某类型.

print_2nd()内的另一个本地变量value,它的类型是int. int 不依赖任何template参数的名称.这样的名称是谓非从属名称(non-dependent names)…Sott Meyers觉得应该叫它..独立名称(independent names)…


现在再来看看为什么编译器不通过上面的代码

当编译器开始解析template print_2nd时,并不知道T是什么东西.这是因为c++在解析模板中遇到一个嵌套从属名称,它便假设这名称不是个类型,除非你告诉它是.所以默认下嵌套从属类型不是类型.

因此只有iter的声明时指出T::const_iterator是个类型时才合理.解决方法就是在T::const_iterator前加上typename.

改正后的代码:

template<typename T>void print_2nd(const T &container){    if(container.size() >= 2) {        typename T::const_iterator iter(container.begin());        iter++;        int value = *iter;        std::cout << value << std::endl;    }}

模板类中的typename

看起来好像只要涉及嵌套从属名称就应该给它的前面加上typename指明它是个类型.不过当然也有例外.

typename不可以出现在基类列表(base classes list)和成员初始化列表(member initialization list)中作为基类修饰符.

例如:

template<typename T>class Son : public Base<T>::mem{public:    explicit Son(int x)    : Base<T>::mem(x)    {        typename Base<T>::mem grand;      // 这里必须使用    }};

不同的编译器对待typename

typename的相关规则在不同的编译器上有不同的实践.某些编译器接受的代码原本该有typename却遗漏了;原本不该有typename却出现了.这意味者typename和嵌套从属名称的互动,在移植上会有让人头疼的一面..

1 0