从特定专业化继承时可访问的模板基类?

Vin*_*ent 14 c++ inheritance language-lawyer template-meta-programming c++11

前几天,我发现这是可能的:

template <class T> struct base {};
struct derived: base<int> {};

int main()
{
    // The base class template is accessible here
    typename derived::base<double> x;

    // from the comments, even this works
    typename derived::derived::base<double>::base<int>::base<void> y;
}
Run Code Online (Sandbox Code Playgroud)

我没有回忆过在cppreference或C++教程中读过这个,或者这是在聪明的模板元编程技巧中被利用的(因为我确信它可以).我有几个问题:

  • 这个东西有特定的名字吗?
  • 它在C++标准和cppreference中记录在哪里?
  • 是否有任何模板元编程技巧利用这个?

cpp*_*ner 5

正如@Nir Friedman 在评论中指出的那样,typename derived::derived::base<double>::base<int>::base<void> y;实际上可能是格式错误的,因为derived::derived::base<double>::base<int>::base被视为base, 每个[class.qual]/2的构造函数。


  • 这个东西有具体的名字吗?

它被称为注入类名称

  • 它在 C++ 标准和 cppreference 中的何处记录?

在标准中:[class]/2指定的名称被视为该类的公共成员。[temp.local]指定类模板的注入类名可以用作模板名类型名

关于 cppreference:它(不完整)记录在http://en.cppreference.com/w/cpp/language/unqualified_lookup#Injected_class_name 中

  • 有没有利用这个的模板元编程技巧?

我不知道任何此类技巧,但在日常使用中,只要在类定义中命名当前类,就会使用注入类名称:

template<class T>
struct A {
    A<T>& operator=(const A<T>&); // injected-class-name as template-name
    A& operator=(A&&); // injected-class-name as type-name
};
Run Code Online (Sandbox Code Playgroud)

后者可能被故意用于缩短成员声明。

基类的注入类名称通常(无意识地)用于成员初始化列表:

struct B : A<int> {
    B() : A() {}
};
Run Code Online (Sandbox Code Playgroud)