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

时间:2018-01-15 18:36:36

标签: c++ c++11 inheritance language-lawyer template-meta-programming

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

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;
}

我不记得曾经在cppreference或C ++教程中阅读过这篇文章,或者这是在巧妙的模板元编程技巧中被利用的(因为我确信它可以)。我有几个问题:

  • 这件事有特定的名字吗?
  • C ++标准和cppreference中记录了哪些内容?
  • 是否有任何模板元编程技巧利用这个?

1 个答案:

答案 0 :(得分:4)

正如comment中@Nir Friedman指出的那样,typename derived::derived::base<double>::base<int>::base<void> y;可能实际上是不正确的,因为derived::derived::base<double>::base<int>::base被视为base的构造函数,每{{3} }}

  
      
  • 这件事有特定的名字吗?
  •   

它被称为 inject-class-name

  
      
  • C ++标准和cppreference中记录了哪些内容?
  •   

在标准中:[class.qual]/2指定将类的名称视为该类的公共成员。 [class]/2指定类模板的inject-class-name可以用作模板名称类型名称

关于cppreference:它在[temp.local]中记录(不完整)。

  
      
  • 是否有任何模板元编程技巧利用这个?
  •   

我不知道任何这样的技巧,但在日常使用中,只要在类定义中命名当前类,就会使用inject-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
};

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

基类的inject-class-name主要用于(无意识地)在成员初始化列表中:

struct B : A<int> {
    B() : A() {}
};