声明template参数时, 前缀关键字class和typename可以互换;

使用关键字typename标识嵌套从属类型名称, 但不需在基类列表和成员初始化列表内使用.

从属名称(dependent names): 模板(template)内出现的名称, 相依于某个模板(template)参数, 如T t;

嵌套从属名称(nested dependent names):从属名称在class内呈嵌套装, 如T::const_iterator ci;

非从属名称(non-dependent names): 不依赖任何template参数的名称, 如int value;

如果不特定指出typename, 嵌套从属名称, 有可能产生解析(parse)歧义.

任何时候在模板(template)中指涉一个嵌套从属类型名称, 需要在前一个位置, 添加关键字typename;

否则报错(GCC): error: need 'typename' before 'T::xxx' because 'T' is a dependent scope

#include <iostream>
#include <string>
#include <vector> using namespace std; template<typename T>
void print2nd(const T& container) {
typename T::const_iterator iter(container.begin()); //未加typename, 报错
++iter;
int value = *iter;
std::cout << value;
} int main () {
vector<int> vi = {,,,,};
print2nd(vi); return ;
}

例外:嵌套从属类型名称, 如果是基类列表(base class list)和成员初值列(member initialization list)中,不使用typename;为什么这里不需要呢?因为编译器知道这里需要的是类型还是变量,(1)基类列表里肯定是类型名,(2)初始化列表里肯定是成员变量名。

#include <iostream>
#include <vector>
using namespace std; struct Number {
Number(int x) {
std::cout << "Number = " << x << std::endl;
}
}; template<typename T>
struct Base{
typedef Number Nested;
}; template<typename T>
class Derived: public Base<T>::Nested { //不用typename
public:
explicit Derived(int x) : Base<T>::Nested(x) { //不用typename
typename Base<T>::Nested temp(); //必须使用
}
}; int main () {
Derived<int> d(); return ;
}

当使用特性类(traits class)时, 必须使用typename, 如

#include <array>
#include <iostream>
using namespace std; template<typename T>
void workWithIter(T iter) {
typedef typename std::iterator_traits<T>::value_type value_type; //使用typename
value_type temp(*iter);
std::cout << "temp = " << temp << std::endl; } int main () {
std::array<int, > ai = {,,,,};
std::array<int, >::iterator aiIter = ai.begin();
workWithIter(aiIter);
return ;
}

另附:

//下面来讨论typename的第二种用法。现在假设我们有一个类如下:
template <typename T> class Y
{
T::iterator *iter;
...
};
/* 我们可能本意是想定义一个迭代器对象,例如我们如果用vector<int>来实例化这个模板,那么iter
则应该是一个迭代器指针,但是,如果我们用下面这个类来实例化这个模板:*/
class cType
{
static int iterator;
...
};
/* 那么T::iterator *iter会被编译器解释为两个数相乘。事实上,C++编译器会采用第二种解释方法
,即使iterator的确是一个类型名。
为了避免这种矛盾,当我们适用qualified dependent name的时候,需要用typename来指出这是一个
类型名.即: */
template <typename T> class Y
{
typename T::iterator *iter;
typedef typename T::iterator iterator; //定义了Y::iterator类型名称
...
};
//typename 指出下面紧跟着的名称是一个类型

C++ 中 typename的更多相关文章

  1. C++中typename和class的区别

    C++中typename和class的区别 在c++Template中很多地方都用到了typename与class这两个关键字,而且好像可以替换,是不是这两个关键字完全一样呢? 相信学习C++的人对c ...

  2. C++中typename关键字的用法

    我在我的 薛途的博客 上发表了新的文章,欢迎各位批评指正. C++中typename关键字的用法

  3. c++中typename和class的区别介绍

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

  4. [Reprint]c++中typename和class的区别介绍

    在c++Template中,很多地方都用到了typename与class这两个关键字,而且好像可以替换,是不是这两个关键字完全一样呢?   相信学习C++的人对class这个关键字都非常明白,clas ...

  5. <转>详解C++的模板中typename关键字的用法

    用处1, 用在模板定义里, 标明其后的模板参数是类型参数. 例如: template<typename T, typename Y> T foo(const T& t, const ...

  6. C++ - 模板(template)中typename的使用方法

    声明template参数时, 前缀关键字class和typename可以互换; 使用关键字typename标识嵌套从属类型名称, 但不需在基类列表和成员初始化列表内使用. 从属名称(dependent ...

  7. vb中typename函数

    适用于获得一个变量的类型名称的, 比如 A 是一个字符串变量,那么 TypeName(A)=String

  8. typename在C++中的用法

    . //在C++中typename一般用来声明模板的模板参数(template parameter): template<typename T> class X; //T是一个模板参数 . ...

  9. [c++] Pieces of knowledge

    再系统地学一遍c++,查缺补漏. wchar_t L'a' stored in wchar_t. size of types cout << numeric_limits<doubl ...

随机推荐

  1. 七个结构模式之外观模式(Facade Pattern)

    定义: 为子系统的一组接口提供一个统一的入口,从而降低系统之间的耦合度,提高子系统的可用性.外观模式又称为门面模式,是迪米特法则的一个体现,主要目的就是降低耦合. 结构图 Facade:抽象外观类,子 ...

  2. Linux学习历程(持续更新整理中)

    1.文件目录操作命令 (1) ls   显示文件和目录列表 a ls -l  显示文件的详细信息 b ls -a 列出当前目录的所有文件,包含隐藏文件. c stat '目录/文件'   显示指定目录 ...

  3. MasonJS – 创建完美的砌体结构网页布局

    MasonJS 插件用来解决目前大多数的网格系统使用中的问题——间距.当使用 Masonry,Isotope 或任何其他网格插件时,布局中会出现空白或边缘参差不齐的情况.MasonJS 可以帮助你填补 ...

  4. 安装 Ubuntu 后的个人常用配置

    在 ASA 猪队友的带领下,拥抱开源世界,用上了Ubuntu.资深强迫症现身说法,配置符合自己使用习惯的Ubuntu. 1. 窗口标题栏显示菜单项 打开系统设置->外观->行为,在[显示窗 ...

  5. PHP代码审计中你不知道的牛叉技术点

    一.前言 php代码审计如字面意思,对php源代码进行审查,理解代码的逻辑,发现其中的安全漏洞.如审计代码中是否存在sql注入,则检查代码中sql语句到数据库的传输 和调用过程. 入门php代码审计实 ...

  6. Troubleshooting FIM: (No Display Name) in FIM Portal

    from: http://social.technet.microsoft.com/wiki/contents/articles/12682.troubleshooting-fim-no-displa ...

  7. Android 短信验证码平台

    1.容联云通讯 (目前只支持国内.收费) http://www.yuntongxun.com/ 2.bmob (目前只支持国内.收费) http://www.bmob.cn/ 3.阿里大鱼(目前只支持 ...

  8. mysql 数据库服务中的应用程序

    mysql 是一个数据库服务,而实现数据库服务是由mysql中的很多子应用程序来完成的(http://dev.mysql.com/doc/refman/5.7/en/programs-overview ...

  9. 网络编程---HTTP

    URL: 什么是URL ? URL的全称是Uniform Resource Locator(统一资源定位符) 通过1个URL,能找到互联网上唯一的1个资源 URL就是资源的地址.位置,互联网上的每个资 ...

  10. 编译生成IOS开发使用的FFmpeg的过程

    前言:本篇随笔纯属是参照<iOS 使用 FFmpeg>的过程,本人自己操作了一遍,但是本人记性不好,觉得这样的过程可以记录在博客中,以后需要可以快速回头翻阅细节.所以特地参考<iOS ...