简体   繁体   English

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

[英]Template class does not see inherited template member

Let me consider a template class which derived from a base template class. 让我考虑一个从基本模板类派生的模板类。 The base class contains a template member. 基类包含模板成员。 In this case, usually members of the base class can be accessed from the derived class using the pointer this . 在这种情况下,通常可以使用指针this从派生类访问基类的成员。 It appears however that this is not the case, when a base member is itself a template function. 然而,当基础成员本身是模板功能时,似乎不是这种情况。

Consider the following code 请考虑以下代码

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

In the main routine the template member increment is called from a variable of type base . main例程中,从类型为base的变量调用模板成员increment This works without any problem. 这没有任何问题。 On the other hand, the member function p() of the deriv class tries to access to the template function increment inherited from base. 另一方面, deriv类的成员函数p()尝试访问从base继承的模板函数increment Using the pointer this as in the commented line above 使用指针this如在上面的注释行

this->increment<1>();

gives the compile error 给出了编译错误

expected primary-expression before ‘)’ token

After trying for a while, I found it possible, as in the code above, to access to the increment function via the scope operator 在尝试了一段时间后,我发现可以通过范围运算符访问increment函数,如上面的代码所示

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

This however explicitly instantiate base with T=int . 然而,这显然是用T=int实例化base If I want to call the increment member from the inherited base<T> , with generic T class as 如果我想从继承的base<T>调用increment成员,使用泛型T

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

I get the same error as above. 我得到与上面相同的错误。

I am using gcc 8.1.1 我正在使用gcc 8.1.1

The question is: why using the pointer this cannot the compiler resolve the inherited member function increment ? 问题是:为什么使用指针this不能编译器解析继承的成员函数increment How can I get instantiate the inherited template function increment , from the inherited class base ? 我怎样才能获得实例继承模板函数increment ,从继承的类base

Edit: I added another case where it fails to compile, better specify the question. 编辑:我添加了另一个无法编译的情况,更好地指定问题。

Edit: small correction in the program, same question. 编辑:程序中的小修正,同样的问题。

Unless you specify otherwise, the compiler assumes that the name you access is not a template, so both < and > are tokenized as less than and greater than signs respectively (the line is parsed as ((this->increment)<1)>() ). 除非您另行指定,否则编译器会假定您访问的名称不是模板,因此<>分别被标记为小于和大于符号(该行被解析为((this->increment)<1)>() )。 This happens because this and base<T> are both dependent on the template parameter T and the compiler cannot look up increment to see if it is a template. 发生这种情况是因为thisbase<T>都依赖于模板参数T ,并且编译器无法查找increment以查看它是否是模板。 This holds for any case where the name on the left of an operator is dependent on any template parameter and the name on the right is template-id (name with <> ). 这适用于任何情况,其中运算符左侧的名称依赖于任何模板参数,右侧的名称是template-id(名称带有<> )。 To solve this problem, you need to use the template keyword 要解决此问题,您需要使用template关键字

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

Why does base<int>::increment<1>(); 为什么base<int>::increment<1>(); compile then? 然后编译? Because it does not depend on T (refers to a known specialization), thus the name increment can be looked up to determine whether it is or is not a template. 因为它不依赖于T (指的是已知的特化),所以可以查找名称increment以确定它是否是模板。
But it won't compile if T is not int . 但如果T不是int ,它将无法编译。 gcc gives the following error gcc给出以下错误
[x86-64 gcc 8.1 #1] error: type 'base<int>' is not a base type for type 'deriv<long long int>'
If base<int>::increment was public static, the code would always compile (not exactly because the compiler would compile about x not being static, but with additional changes it would). 如果base<int>::increment是public static,那么代码总是会编译(不完全是因为编译器会编译x不是静态的,但会有额外的更改)。

Calling this->increment<1>() is invalid because increment is a dependent function template. 调用this->increment<1>()无效,因为increment是依赖函数模板。 You need therefore need to use the template keyword: 因此,您需要使用template关键字:

this->template increment<1>();

Your using directive and base<int>::increment<1>() call are also not correct. 您的using指令和base<int>::increment<1>()调用也不正确。 If deriv is intantiated with a type other than int neither of those will work. 如果deriv是intantiated比其他类型int那些都将工作。 You should use T instead of int in both of those. 你应该在这两个中使用T而不是int When doing so the call to base<T>::increment<1>() will become invalid for the same reason this->increment<1>() is invalid. 执行此操作时,对base<T>::increment<1>()的调用将因同一原因this->increment<1>()无效而变为无效。 You need the template keyword there as well: 那里你也需要template关键字:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM