C++ typename 模板参数和标识嵌套依赖类型名的作用

模板类型参数

在泛型编程中,typename 和 class 都可以作为模板类型参数,是一样的。

template<class T>	//等同于 template<typename T>
class Animal {
public:
	T name;
};

在模板中标识嵌套依赖类型名称

规则:不管是在模板函数还是模板类中,如果有使用 嵌套依赖类型名称 nested dependent type name 的话,都需要在他的前面加上 typename。

先不管概念,直接从实际出发看看 typename 发挥了什么作用:

class Cat {
public:
    class Color{};
	using Weight = int;	typedef int Age;	//和Color一样,属于内部类型,在模板类中作为类型使用前面要加上 typename
};

template<class T>
class Animal {
public:
    T::Color* p1;					//(1) 	×
    typename T::Color* p2;			//(2)	√
};

int main(){
	Animal<Cat> ani;
}

在模板类 Animal 中的代码 (1),T::Color* CatColor 看起来是声明一个 T::Color 指针类型的对象,然而在编译器的眼里却不是这样的。模板函数/类的代码在编译过程中,并不知道模板类型参数是什么,要等到实际运行了才知道。这就导致了编译器不知道 T::Color 是类型还是类变量。如果 T::Color 是类变量,p1 是一个全局变量,这条语句就是乘法*操作了。

这时候就需要用到 typename 了,将他放到嵌套依赖类型名称的前面,就能显式告诉编译器,这是一个类型,而不是变量,从而正确实现代码功能,比如上述代码中的 (2)。

模板类中,可以使用模板类型参数本身,也可以使用参数内部定义的类,如:using Weight = inttypedef int Age 定义的类都可以在模板类中使用。

如果没有加上 typename 关键字:

默认情况下,C++ 语言假定通过作用域运算符访问的名字不是类型。

不能使用 typename 的地方

typename 可以出现在函数体内,可以出现在函数返回类型前,可以出现在函数参数前。但是当子类继承的父类是嵌套依赖类型名称的时候,typename 不能出现在类的基类列表以及成员初始化列表中作为父类的修饰符。

template<class T>
class Animal {
};
//Size方法是模板类型参数T的内部类
template <typename T>
class Cat : public Animal<T>::Size{		//Animal<T>::Size 前不可用 typename 修饰
public:
    Cat(int m) : Animal<T>::Size(m){	//Animal<T>::Size 前不可用 typename 修饰
        //函数体中可以使用
    }
};

个人认为,嵌套依赖类型名称在子类的父类列表中表示父类,在成员初始化列表中表示类的构造函数,都是类型,没有歧义,所以也就不需要 typename


网上关于 typename 的文章绝大部分都是出自 Effective C++ 中的条款 42。书中关于相关概念有如下描述:

一个 template(模板)中的依赖于一个 template parameter(模板参数)的名字被称为 dependent names(依赖名字)。当一个 dependent names(依赖名字)嵌套在一个 class(类)的内部时,我称它为 nested dependent name(嵌套依赖名字)。一个涉及到一个 type(类型)的 nested dependent name(嵌套依赖名字)就是 nested dependent type name(嵌套依赖类型名)。

又是依赖又是嵌套的,这么绕口,想了很久没想明白,书中也没有具体展开,也没所谓了。
只要知道这个就行了:嵌套依赖类型名称指的是,在模板类中使用的模板类型参数 T 的内部类 C。(C是Y的嵌套依赖类型名称)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值