热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

STL中的typename与class关键字

在泛型编程的形参表中,关键字typename和class具有相同的含义,可以相互使用,两个关键字都可以在同一模板形参表中使用:  1. typename用在模板定义里,标明其后的模

在泛型编程的形参表中,关键字typename和class具有相同的含义,可以相互使用,两个关键字都可以在同一模板形参表中使用:  

1.  typename用在模板定义里,标明其后的模板参数是类型参数

[html] 
view plain
copy

  1. template<typename T,class U> calc (const T&, const U& );   
  2.   
  3. // 定义一个返回参数中较大者的通用函数  
  4. template <typename T>  
  5. const T& max(const T& x, const T& y)  
  6. {  
  7.   if (y < x) {  
  8.     return x;  
  9.   }  
  10.   return y;  
  11. }  

这种情况下,typename可用另一个的等效关键字class代替,如下片段所示:

[html] 
view plain
copy

  1. // 定义一个返回参数中较大者的通用函数  
  2. template <class T>  
  3. const T& max(const T& x, const T& y)  
  4. {  
  5.   if (y < x) {  
  6.     return x;  
  7.   }  
  8.   return y;  
  9. }  

   引入这个关键字主要是为了避免class可能给人带来的混淆:

 使用关键字typdef 代替关键字class制定模板类型形参也许更为直观,毕竟,可以使用内置类型(而不仅仅只是类类型)作为实际的类型形参,而且,更清楚地声明后面的名字是一个类型名。关键字typedef作为标准c++的组成部分假如到c++中的,因此旧的程序可能只是用class用来修饰泛型编程的形参类型。

2, 模板中标明“内嵌依赖类型名”:内嵌依赖类型名(nested dependent type name)

   .本来typename的用法就是这么简单, 但是STL源代码中还有typename的一种不常见的用法:

例1:

请看SGI STL里的一个例子, 只是STL中count范型算法的实现:

[html] 
view plain
copy

  1. template <class _InputIter, class _Tp>  
  2. typename iterator_traits<_InputIter>::difference_type  
  3. count(_InputIter __first, _InputIter __last, const _Tp& __value) {  
  4.   __STL_REQUIRES(_InputIter, _InputIterator);  
  5.   __STL_REQUIRES(typename iterator_traits<_InputIter>::value_type,  
  6.                  _EqualityComparable);  
  7.   __STL_REQUIRES(_Tp, _EqualityComparable);  
  8.   typename iterator_traits<_InputIter>::difference_type __n = 0;  
  9.   for ( ; __first != __last; ++__first)  
  10.     if (*__first == __value)  
  11.       ++__n;  
  12.   return __n;  
  13. }  

这里有三个地方用到了typename:返回值、参数、变量定义。分别是:

    typename iterator_traits<_InputIter>::difference_type

    typename iterator_traits<_InputIter>::value_type

    typename iterator_traits<_InputIter>::difference_type __n = 0;

    difference_type, value_type就是依赖于_InputIter(模板类型参数)的类型名。源码如下:

[html] 
view plain
copy

  1. template <class _Iterator>  
  2. truct iterator_traits {  
  3.  typedef typename _Iterator::iterator_category iterator_category;  
  4.  typedef typename _Iterator::value_type        value_type;  
  5.  typedef typename _Iterator::difference_type   difference_type;  
  6.  typedef typename _Iterator::pointer           pointer;  
  7.  typedef typename _Iterator::reference         reference;  
  8. ;  

内嵌是指定义在类名的定义中的。以上difference_type和value_type都是定义在iterator_traits中的。

    依赖是指依赖于一个模板参数。typename iterator_traits<_InputIter>::difference_type中difference_type依赖于模板参数_InputIter.

    类型名是指这里最终要指出的是个类型名,而不是变量。例如iterator_traits<_InputIter>::difference_type完全有可能是类iterator_traits<_InputIter>类里的一个static对

    象。而且当我们这样写的时候,C++默认就是解释为一个变量的。所以,为了和变量区分,必须使用typename告诉编译器。

    那么是不是所有的T::type_or_variable, 或者tmpl:type_or_variable都需要使用typename呢?不是,有以下两个例外。

3 例外

    (1)类模板定义中的基类列表。

    例如

[html] 
view plain
copy

  1. template<class T>  
  2. class Derived: public Base<T>::XXX  
  3. {  
  4. &#8230;  
  5. }  

   (2)类模板定义中的初始化列表。

[html] 
view plain
copy

  1. Derived(int x) : Base<T>::xxx(x)  
  2. {  
  3. &#8230;  
  4. }  

为什么这里不需要呢?因为编译器知道这里需要的是类型还是变量,

    (1)基类列表里肯定是类型名,(2)初始化列表里肯定是成员变量名。

例2:

在模板定义内部指定类型。如下面代码:

[html] 
view plain
copy

  1. typename<class Parm,class U>  
  2. Parm fcn(Parm* array,U value)  
  3. {  
  4.      Parm::size_type *p;  
  5.      //如果Parm::size_type是一个类型,这句话的意思就是声明一个变量  
  6.      //如果如果Parm::size_type是一个变量(对象),这句话的意思就是乘法运算  
  7. }  

假如像上面的代码一样在模板中使用这种语句,则编译器将无法辨别Parm::size_type是一个变量还是一个类型。所以必须显式的告诉编译器:

Parm::size_type是一个类型:

   则函数模板变为如下所示:

[html] 
view plain
copy

  1. typename<class Parm,class U>  
  2. Parm fcn(Parm* array,U value)  
  3. {  
  4.     typename Parm::size_type *p;  
  5. }  

推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Ihavethefollowingonhtml我在html上有以下内容<html><head><scriptsrc..3003_Tes ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
author-avatar
mobiledu2502924857
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有