模板类看不到继承的模板成员

时间:2018-06-24 18:14:34

标签: c++ templates

让我考虑一个从基本模板类派生的模板类。基类包含一个模板成员。在这种情况下,通常可以使用指针this从派生类访问基类的成员。但是,当基本成员本身是模板函数时,情况并非如此。

考虑以下代码

#include <iostream>

template <class T>
struct base {
  T x;
  base() { x = 10; }
  template <unsigned int N>
  void increment() { x += N; }
};

template <class T>
struct deriv : public base<T> {
  using base<T>::base;

  void p()
  {
    using namespace std;
    cout << this->x << endl;
    base<int>::increment<1>();
    // The following statement causes the compile error:
    // expected primary-expression before ‘)’ token
    // this->increment<1>();
    // Also the following statement gives error
    // base<T>::increment<1>();
    cout << this->x << endl;
  }
};

int main()
{
  using namespace std;

  base<int> A;
  cout << A.x << endl;
  A.increment<1>();
  cout << A.x << endl;

  deriv<int> B;
  B.p();

  return 0;
}

main例程中,从类型increment的变量调用模板成员base。这没有任何问题。 另一方面,p()类的成员函数deriv尝试访问从基继承的模板函数increment。如上面的注释行中那样使用指针this

this->increment<1>();

给出编译错误

expected primary-expression before ‘)’ token

尝试了一段时间之后,我发现可以像上面的代码一样通过范围运算符访问increment函数

base<int>::increment<1>();

这将用base显式实例化T=int。如果我想从继承的increment调用base<T>成员,将通用T类作为

base<T>::increment<1>();

我收到与上述相同的错误。

我正在使用gcc 8.1.1

问题是:为什么编译器无法使用指针this来解析继承的成员函数increment?如何从继承的类increment实例化继承的模板函数base

编辑:我添加了另一种情况,即它无法编译,最好指定问题。

编辑:程序中的小更正,同样的问题。

2 个答案:

答案 0 :(得分:2)

除非另行指定,否则编译器会假设您访问的名称不是模板,因此<>都分别标记为小于和大于符号(该行被解析为((this->increment)<1)>())。发生这种情况是因为thisbase<T>都依赖于模板参数T,并且编译器无法查找increment来查看它是否是模板。在任何情况下,运算符左侧的名称取决于任何模板参数,而右侧的名称为template-id(带有<>的名称),则适用。要解决此问题,您需要使用template关键字

base<T>::template increment<1>();
this->template increment<1>();

为什么base<int>::increment<1>();会进行编译?由于它不依赖于T(指的是已知的专业化知识),因此可以查询名称increment以确定它是否是模板。
但是如果T不是int,它将不会编译。 gcc出现以下错误
[x86-64 gcc 8.1 #1] error: type 'base<int>' is not a base type for type 'deriv<long long int>'
如果base<int>::increment是公共静态的,则代码将始终进行编译(不完全是因为编译器会编译x不是静态的,而是会进行其他更改)。

答案 1 :(得分:1)

调用this->increment<1>()是无效的,因为increment是从属函数模板。因此,您需要使用template关键字:

this->template increment<1>();

您的using指令和base<int>::increment<1>()调用也不正确。如果deriv的类型不是int,则两者都不起作用。两者都应使用T而不是int。这样做时,由于base<T>::increment<1>()无效的相同原因,对this->increment<1>()的调用将变为无效。您还需要在那里的template关键字:

base<T>::template increment<1>();