zoukankan      html  css  js  c++  java
  • typename的一些用法和注意问题

    一些关键概念
    在我们揭开真实原因的面纱之前,先保持一点神秘感,因为为了更好的理解C++标准,有几个重要的概念需要先行介绍一下。

    限定名和非限定名
    限定名(qualified name),故名思义,是限定了命名空间的名称。看下面这段代码,cout和endl就是限定名:

    #include <iostream>
    int main()  {
        std::cout << "Hello world!" << std::endl;
    
    }

    cout和endl前面都有std::,它限定了std这个命名空间,因此称其为限定名。
    如果在上面这段代码中,前面用using std::cout;或者using namespace std;,然后使用时只用cout和endl,它们的前面不再有空间限定std::,所以此时的cout和endl就叫做非限定名(unqualified name)。

    依赖名和非依赖名
    依赖名(dependent name)是指依赖于模板参数的名称,而非依赖名(non-dependent name)则相反,指不依赖于模板参数的名称。看下面这段代码:

    template <class T>
    struct MyClass {
        int i;
        vector<int> vi;
        vector<int>::iterator vitr;
        T t;
        vector<T> vt;
        vector<T>::iterator viter;
    
    };

    因为是内置类型,所以类中前三个定义的类型在声明这个模板类时就已知。然而对于接下来的三行定义,只有在模板实例化时才能知道它们的类型,因为它们都依赖于模板参数T。因此,T, vector<T>和vector<T>::iterator称为依赖名。前三个定义叫做非依赖名。
    更为复杂一点,如果用了typedef T U; U u;,虽然T没再出现,但是U仍然是依赖名。由此可见,不管是直接还是间接,只要依赖于模板参数,该名称就是依赖名。

    typename的标记作用:
    结束以上两个个概念的讨论,让我们接着揭开typename的神秘面纱。
    一个例子
    在Stroustrup起草了最初的模板规范之后,人们更加无忧无虑的使用了class很长一段时间。可是,随着标准化C++工作的到来,人们发现了模板这样一种定义:

    template <typename T>
    void foo() {
        T::iterator iter;
        // ...
    }

    在上例代码中T本身已经是模板的类型参数,它只有等到模板实例化时才会知道是哪种类型,更不用说由T定义的内部的iterator

    编译器不知道第三行代码到底是,定义一个变量还是定义一个新类型,这样同一行代码能以两种完全不同的方式解释,而且在模板实例化之前,完全没有办法来区分它们,这绝对是滋生各种bug的温床。这时C++标准委员会再也忍不住了,与其到实例化时才能知道到底选择哪种方式来解释以上代码,委员会决定引入一个新的关键字,这就是typename

    c++标准定义到:

    对于用于模板定义的依赖于模板参数的名称,只有在实例化的参数中存在这个类型名,或者这个名称前使用了typename关键字来修饰,编译器才会将该名称当成是类型。除了以上这两种情况,绝不会被当成是类型。

    因此,如果你想直接告诉编译器T::iterator是类型而不是变量,只需用typename修饰:

    template <typename T>
    void foo() {
        typename T::iterator iter;
        // ...
    }

    通过加上typename关键字,这样编译器就可以确定T::iterator是一个类型,而不再需要等到实例化时期才能确定,因此消除了歧义。

  • 相关阅读:
    完整性检查工具Nabou
    Linux下使用网上银行
    戏说Linux商用数据库
    开源数据库“五虎将”
    搜寻Linux软件实用指南
    认识Linux瘦客户机
    一款开源Office软件---Lotus Symphony在Linux系统下的应用
    Leetcode-967 Numbers With Same Consecutive Differences(连续差相同的数字)
    Leetcode-965 Univalued Binary Tree(单值二叉树)
    Leetcode-966 Vowel Spellchecker(元音拼写检查器)
  • 原文地址:https://www.cnblogs.com/litifeng/p/13042863.html
Copyright © 2011-2022 走看看