zoukankan      html  css  js  c++  java
  • 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
     }
    }

    这样就对了。

  • 相关阅读:
    实验四 决策树算法及应用
    实验三 朴素贝叶斯算法及应用
    实验二 K-近邻算法及应用
    实验一 感知器及其应用
    实验三
    实验二 结构化分析与设计
    实验一 Visio的使用
    ATM管理系统
    流程图与活动图的区别与联系
    四则运算
  • 原文地址:https://www.cnblogs.com/yutongqing/p/6721323.html
Copyright © 2011-2022 走看看