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
     }
    }

    这样就对了。

  • 相关阅读:
    python3.8安装flask出现错误“ModuleNotFoundError: No module named '_ctypes'”
    利用virtualenvwrapper创建虚拟环境出现错误“/usr/bin/python: No module named virtualenvwrapper”
    CentOS7 下升级Python版本
    Python 定义动态变量
    Linux常用命令
    项目经验之:项目用到LinQ (总结)
    ListBox操作一些总结
    项目经验之:如CSDN一样的分页,我能否做这样的分页吗??????
    记上一笔,listbox展示项中,隐藏其中一项
    项目经验之:SQL一些简单问题中可以使用的技巧
  • 原文地址:https://www.cnblogs.com/yutongqing/p/6721323.html
Copyright © 2011-2022 走看看