Typename和Class在声明模板时的区别
声明template参数时,前缀关键词class和typename可互换。也就是说以下两个没有区别:
(1)template<class T>class Widget;
(2)template<typename>class Widget。
然而C++并不总是把class和typename视为等价。有时一定得使用typename。
这种时机就是:任何时候当想要在template中指涉一个嵌套从属类型名称,就必须在紧邻它的前一个位置放上关键字typename,只有如下一个例外:不得在base class list(基类列)或member initialization list(成员初值列)内以它作为base class修饰符。其中:template内出现的名称如果相依于某个template参数,称之为从属名称。如果从属名称在class内呈嵌套状,我们称它为嵌套从属名称。C::const_iterator(看下面例子)就是这样的一个名称。实际上它还是个嵌套从属类型名称,也就是个嵌套从属名称并且指涉某类型。看下面例子:
template <typename C>
void print2nd(const C& container)
{
if(container.size()>=2)
{
C::const_iterator iter(container.begin());
++iter;
int value = *iter;
cout<<value<<endl;
}
}
嵌套从属名称有可能引起解析困难。如下面的例子(将上面的改一下):
template <typename C>
void print2nd(const C& container)
{
C::const_iterator* x;
...
}
按照正常的理解我们应该是声明了一个x的局部变量,但是前提是我们知道C::const_iterator是个类型,但是万一不是呢,比如C是个类并且它有一个const_iterator的静态成员变量呢而且x又是一个全局变量,那么上面的就是一个相乘的动作,即C::const_iterator乘以x。引起歧义。
在我们知道C是什么之前,没有任何办法可以知道C::const_iterator是否是一个类型。而当编译器开始解析template print2nd时,尚未知C是什么东西。C++有个规则可以解析此一歧义状态:如果解析器在template中遭遇一个嵌套从属名称,它便假设这名称不是一个类型,除非你告诉它是。所以缺省情况下嵌套从属名称不是类型。此规则有个例外,稍后会谈到。我们告诉它是只需在C::const_iterator前加上关键字typename即可。
注意typename只被用来验明嵌套从属类型名称;其他名称不该有它存在。如下面的例子:
template<typename C>
void f(const C& container,typename C::iterator iter)。参数中第一个不是嵌套从属类型名称,所以不需要关键字typename,而第二个需要。
“typename必须作为嵌套从属类型名称的前缀词”这一规则的例外是,typename不可以出现在base classes list内的嵌套从属类型名称之前,也不可在member initalization list(成员初始列)中作为base class修饰符。例如:
template<typename T>
class Derived:public Base<T>::Nested //base list中不允许"typename"
{
public:
explicit Derived(int x)
:Base<T>::Nested(x) //mem init list中不允许有"typename"
{
typename Base<T>::Nested temp; //这个一定要有"typename"
}
}
最后声明一点:以上讲的在VC++ 6.0下不适用,也就是说在VC下不用typename修饰嵌套从属类型,编译器也不会抱怨,但是在gcc内核下就会发生抱怨。
参考文献:《Effective C++》
Typename和Class在声明模板时的区别相关推荐
- Vue里标签嵌套限制问题解决------解析DOM模板时注意事项:
Vue里标签嵌套限制问题解决------解析DOM模板时注意事项: 参考文章: (1)Vue里标签嵌套限制问题解决------解析DOM模板时注意事项: (2)https://www.cnblogs. ...
- java 定义变量时 赋值与不赋值_探究Java中基本类型和部分包装类在声明变量时不赋值的情况下java给他们的默认赋值...
探究Java中基本类型和部分包装类在声明变量时不赋值的情况下java给他们的默认赋值 当基本数据类型作为普通变量(八大基本类型: byte,char,boolean,short,int,long,fl ...
- warning C4091: “typedef ”: 没有声明变量时忽略“_matcher”的左侧
C++ 警告 warning C4091: "typedef ": 没有声明变量时忽略"_matcher"的左侧 typedef struct _matche ...
- [react] 在React中声明组件时组件名的第一个字母必须是大写吗?为什么?
[react] 在React中声明组件时组件名的第一个字母必须是大写吗?为什么? 必须,React根据首字母是否大写来区分react组件还是dom元素 个人简介 我是歌谣,欢迎和大家一起交流前后端知识 ...
- [vue]vue渲染模板时怎么保留模板中的HTML注释呢?
[vue]vue渲染模板时怎么保留模板中的HTML注释呢? <template comments>... </template> 个人简介 我是歌谣,欢迎和大家一起交流前后端知 ...
- RabbitMQ 声明Queue时的参数们的Power
RabbitMQ 声明Queue时的参数们的Power 参数们的Power 在声明队列的时候会有很多的参数 public static QueueDeclareOk QueueDeclare(this ...
- html使用thymeleaf模板时,获取数据库中字符串值,拆分为list根据下标获取对应的值的方法
1. 需求 html使用thymeleaf模板时,获取数据库中字符串值,拆分为list根据下标获取对应的值的方法 2. 方法 2.1 参考官网:https://www.thymeleaf.org/do ...
- 下载、安装Ctex及编译自动化学报模板时错误的解决
一.下载 直接在清华源下载 https://mirrors.tuna.tsinghua.edu.cn/ctex/legacy/2.9/ 选择 二.安装 安装一般直接都下一步就行,可以自己修改安装路径, ...
- java 基本类型 不赋值_探究Java中基本类型和部分包装类在声明变量时不赋值的情况下java给他们的默认赋值...
探究Java中基本类型和部分包装类在声明变量时不赋值的情况下java给他们的默认赋值 当基本数据类型作为普通变量(八大基本类型: byte,char,boolean,short,int,long,fl ...
最新文章
- 五个运动员参加比赛根据他们说的话判断结果
- HTTP权威指南记录 ---- HTTP概述
- 钟国晨 160809323
- 【Git】GitHub主页从Dark调回Light的方法
- python中while的用法_Python学习笔记之While循环用法分析
- pythonkeywordis与 ==的差别
- [转载]表的设计命名的十个注意点
- C系新版凯立德推荐版本G1036
- 使用 DiskMaker X 轻松制作 Yosemite 安装 U 盘(引)
- 信息可视化中的重要准则——以扇贝单词app中的可视化为例
- python 爬虫3 新浪微博 爬虫 实战
- 揭开LiteOS的神秘面纱
- 成功解决 ValueError: Not a TBLoader or TBPlugin subclass: <class ‘tensorboard_plugin_wit.wit_plugin_load
- 为什么Linkerd不使用Envoy
- c语言间隔符号的作用,C语言教学(二)常见的符号
- html中微博发布怎么做,js实现微博发布小功能
- java中gui_java中GUI是什么意思?详细图解
- 10-221 在员工表中查询入职最晚的员工的编号,姓名和入职日期
- USB无线网卡和PCI-E无线网卡
- java 读取手机文件_Android获取手机文件夹及文件列表的方法