模板和名称解析

参考:Templates and Name Resolution

名称类型

在模板定义中分为3种类型名称:

  1. 局部声明名称,包括模板名以及在模板定义中声明的名称
  2. 模板定义之外的封闭作用域中的名称
  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.");
}