模板和名称解析
参考:Templates and Name Resolution
名称类型
在模板定义中分为3
种类型名称:
- 局部声明名称,包括模板名以及在模板定义中声明的名称
- 模板定义之外的封闭作用域中的名称
- 以某种方式依赖于模板参数的名称,称为依赖名称
模板的名称解析规则主要处理第三类依赖名称,因为编译器在模板被实例化之前对这些名称知之甚少,因为它们可能是完全不同的类型,具体取决于使用的模板参数
依赖名称可能使用如下几种方式定义:
- 使用模板参数本身定义
T
- 限定名的限定部分包含了依赖类型
T::myType
- 限定名的非限定部分包含了依赖类型
N::T
- 基于依赖类型的
const/volatile
定义
const T
- 基于依赖类型的指针、引用、数组和函数指针类型
T *、T &、T [10]、T (*)()
- 大小基于模板参数的数组
template <int arg> class X {
int x[arg] ; // dependent type
}
- 从模板参数构造的模板类型
T<int>, MyTemplate<T>
类型依赖和值依赖
- 依赖于类型参数的模板,称为类型依赖
- 依赖于值参数的模板,称为值依赖
依赖类型名称解析
参考:Name Resolution for Dependent Types
在模板定义中使用typename
作为限定名,告诉编译器给定的限定名称标识类型
template <class T>
class X
{
public:
typename T::myType f(typename T::myType* mt) {
mt->aa = 3;
return *mt;
}
};
class Yarg
{
public:
struct myType {
int aa;
};
};
int main()
{
X<Yarg> x;
Yarg::myType type = x.f(new Yarg::myType());
std::cout <<type.aa<<std::endl;
printf("Name resolved by using typename keyword.");
}