C++模板学习之typename

C++模板给这门编程语言带来了全新的强大的能力。于是能够进行所谓的模板元编程。因为人们发现,使用模板可以将一些逻辑让编译器在编译期间内就完成,从而避免错误被漏到了运行时。

学好模板对理解C++开发以及理解都有非常大的好处。一些著名的C++库如STL、boost等将模板的特性使用的淋漓尽致。

从头学习模板,先看看如何定义一个模板。模板的声明使用如下形式:

template<typename T> class Widget; // uses "typename"

这就表明Widget是一个模板类,在该类中,会使用到类型为T的某个类型。这个类型T由使用模板类Widget的使用者在使用时确定。当然,模板的声明也可以使用关键字class代替typename进行

template<class T> class Widget; // uses "typename"

但是,《Effective C++》中建议我们尽量使用typename而不是class来声明一个模板。因为class给人的感觉总像是T应该是一个类,或者说是用户自定义的类型,而typename则更像是表明T可以是任意一种类型。虽然在C++编译器看来,这两种声明方式没有任何的区别,其意义是完全一样的。

不过,typename关键字在模板中还有另一种用法,以下例子依然来自于《Effective C++》:

template<typename C> // print 2nd element in
void print2nd(const C& container) // container;
{ 
 // this is not valid C++!
 if (container.size() >= 2) {
  C::const_iterator iter(container.begin()); // get iterator to 1st element
  ++iter; // move iter to 2nd element
  int value = *iter; // copy that element to an int
  std::cout << value; // print the int
 }
}

此处类型C期望是一个容器性质的类,比如STL中的那些容器,pritn2nd模板函数试图将容器中的第二个元素打印出来,于是,在函数内定义了一个局部变量iter,一个const迭代器,来定位到容器中的第二个元素。但是这段代码却是不会被编译器认可的,因为我们想当然地将C::const_iterator认为是一个类型了,按照我们对容器的印象(比如std::vector<T>::const_iterator)。然而编译器并不知道C是个什么类型,C::const_iterator完全可能是C类型的一个成员变量。试想如果模板函数中是这样的:

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

如果C::const_iterator是一个类型,则定义了一个C::const_iterator类型的指针x,而如果C::const_iterator是类型C的一个成员变量呢,如果x正好是一个全局变量呢,这个表达式就是两个变量的乘积了。此处产生歧义的原因就在于C::iterator意义不明确,它依赖于模板参数,我们将其称为嵌套依赖名字(nested dependent name),为了消除歧义,C++规定,对于嵌套依赖名字,统统不解释为类型,除非显示声明。这就是为什么说上面那段代码有问题,因为编译器不认为C::const_iterator是一个类型。那么如何显示声明C::iterator为一个类型呢,就是使用typename关键字!

template<typename C> // print 2nd element in
void print2nd(const C& container) // container;
{ 
 // this is not valid C++!
 if (container.size() >= 2) {
  typename C::const_iterator iter(container.begin()); // get iterator to 1st element
  ++iter; // move iter to 2nd element
  int value = *iter; // copy that element to an int
  std::cout << value; // print the int
 }
}

这样就对了。

posted @ 2017-04-17 09:19  重复啦  阅读(6231)  评论(0编辑  收藏  举报