C++typename的由来和用法

前言html

   在C++模板函数的使用过程当中,咱们常常能够看到一个typename的使用,例如这样的操做linux

可是除此以外,咱们也会常常看到这样的用法c++

那么这里就要问你们,这C++相似的用法下有什么区别呢,且听我细细道来。编程


做者:良知犹存微信

转载受权以及围观:欢迎添加微信公众号:羽林君app


由来分析框架

   "typename"是一个C++程序设计语言中的关键字。当用于泛型编程时是另外一术语"class"的同义词。这个关键字用于指出模板声明(或定义)中的非独立名称(dependent names)是类型名,而非变量名。编程语言

    

    咱们常常会这么用 typename,这是一项C++编程语言的泛型编程(或曰“模板编程”)的功能,typename关键字用于引入一个模板参数。函数

template <typename T> const T& max(const T& x, const T& y) { if (y < x) { return x; } return y; } 

在模板定义语法中关键字 class 与 typename 的做用彻底同样spa

template<class T> const T& max(const T& x, const T& y) { if (y < x) { return x; } return y; } 

    这里 class 关键字代表T是一个类型,后来为了不 class 在这两个地方的使用可能给人带来混淆,因此引入了 typename 这个关键字,它的做用同 class 同样代表后面的符号为一个类型。

    那class使用就够了,为何又引入了新的关键词 typename ,关于这个问题,Stan Lippman 曾在其博客中表示,最先 Stroustrup 使用 class 来声明模板参数列表中的类型是为了不增长没必要要的关键字;后来委员会认为这样混用可能形成概念上的混淆才加上了 typename 关键字。

        而使用 typename 的做用就是告诉 c++ 编译器,typename 后面的字符串为一个类型名称,而不是成员函数或者成员变量,这个时候若是前面没有 typename,编译器没有任何办法知道 T::LengthType 是一个类型仍是一个成员名称(静态数据成员或者静态函数),因此编译不可以经过。

问题浮现

那么问题来了,什么状况下,class定义以后,编译不能经过呢?

template<typename T>
void fun(const T& proto){


        T::const_iterator it(proto.begin());
}

发生编译错误是由于编译器不知道T::const_iterator是个类型。万一它是个变量呢? T::const_iterator的解析有着逻辑上的矛盾: 直到肯定了T是什么东西,编译器才会知道T::const_iterator是否是一个类型; 然而当模板被解析时,T仍是不肯定的。这时咱们声明它为一个类型才能经过编译:

    并且在模板实例化以前,彻底没有办法来区分它们,这绝对是滋生各类bug的温床。这时C++标准委员会再也忍不住了,与其到实例化时才能知道到底选择哪一种方式来解释以上代码,委员会决定引入一个新的关键字,这就是typename

千呼万唤始出来,咱们来看看C++标准:

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

所以,若是你想直接告诉编译器 T::const_iterator 是类型而不是变量,只需用 typename修饰:

typename    T::const_iterator it(proto.begin());

    这样编译器就能够肯定T::const_iterator是一个类型,而再也不须要等到实例化时期才能肯定,所以消除了前面提到的歧义。

嵌套从属类型

事实上类型T::const_iterator依赖于模板参数T, 模板中依赖于模板参数的名称称为从属名称(dependent name), 当一个从属名称嵌套在一个类里面时,称为嵌套从属名称(nested dependent name)。 其实T::const_iterator仍是一个嵌套从属类型名称(nested dependent type name)。

嵌套从属名称是须要用typename声明的,其余的名称是不能够用typename声明的。好比下面是一个合法的声明:

template<typename T> void fun(const T& proto ,typename  T::const_iterator it); 

使用

    在定义类模板或者函数模板时,typename 和 class 关键字均可以用于指定模板参数中的类型。也就是说,如下两种用法是彻底等价的。

template<typename T> /* ... */; template<class T> /* ... */; 

既然typename关键字已经存在,并且它也能够用于最多见的指定模板参数,那么为何不废除class这一用法呢?答案其实也很明显,由于在最终的标准出来以前,全部已存在的书、文章、教学、代码中都是使用的是class,能够想像,若是标准再也不支持class,会出现什么状况。

    使用关键字typename代替关键字class指定模板类型形参更为直观,毕竟,可使用内置类型(非类类型)做为实际的类型形参,并且,typename更清楚地指明后面的名字是一个类型名。可是,关键字typename是做为标准C++的组成部分加入到C++中的,所以旧的程序更有可能只用关键字class

这就是我分享的c++的typename,此外若是你们有什么更好的思路,也欢迎分享交流哈。

END

推荐阅读

【1】linux开发各类I/O操做简析,以及select、poll、epoll机制的对比

【2】嵌入式底层开发的软件框架简述 

【3】CPU中的程序是怎么运行起来的 必读
【4】什么?还不懂c++vector的用法,你凭什么勇气来的!
【5】阶段性文章总结分析

本公众号所有原创干货已整理成一个目录,回复[ 资源 ]便可得到。

参考连接:

https://liam.page/2018/03/16/keywords-typename-and-class-in-Cxx/

https://harttle.land/2015/09/09/effective-cpp-42.html

http://feihu.me/blog/2014/the-origin-and-usage-of-typename/

更多分享,扫码关注我

相关文章
相关标签/搜索