【问题标题】:Template class does not see inherited template member模板类看不到继承的模板成员
【发布时间】:2018-12-03 09:25:52
【问题描述】:

让我考虑一个从基模板类派生的模板类。基类包含一个模板成员。在这种情况下,通常可以使用指针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 例程中,模板成员incrementbase 类型的变量中调用。这没有任何问题。 另一方面,deriv 类的成员函数p() 尝试访问从基类继承的模板函数increment。在上面的注释行中使用指针this

this->increment<1>();

给出编译错误

expected primary-expression before ‘)’ token

尝试了一段时间,发现可以通过作用域操作符访问increment函数

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

然而,这将使用T=int 显式实例化base。如果我想从继承的base&lt;T&gt; 中调用increment 成员,使用泛型T 类作为

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

我得到与上面相同的错误。

我使用的是 gcc 8.1.1

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

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

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

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

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

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

    那为什么base&lt;int&gt;::increment&lt;1&gt;(); 会编译呢?因为它不依赖于T(指一个已知的特化),所以可以通过查找increment这个名字来判断它是否是一个模板。
    但如果T 不是int,它将无法编译。 gcc 给出以下错误
    [x86-64 gcc 8.1 #1] error: type 'base&lt;int&gt;' is not a base type for type 'deriv&lt;long long int&gt;'
    如果base&lt;int&gt;::increment 是公共静态的,则代码将始终编译(不完全是因为编译器会编译x 不是静态的,但会进行额外的更改)。

    【讨论】:

    • 感谢您的解决方案,不知道这种语法。
    【解决方案2】:

    调用this-&gt;increment&lt;1&gt;() 无效,因为increment 是一个依赖函数模板。因此您需要使用template 关键字:

    this->template increment<1>();
    

    您的using 指令和base&lt;int&gt;::increment&lt;1&gt;() 调用也不正确。如果deriv 被实例化为int 以外的类型,那么这些都不起作用。你应该在这两个中使用T 而不是int。这样做时,对base&lt;T&gt;::increment&lt;1&gt;() 的调用将因为this-&gt;increment&lt;1&gt;() 无效的原因而变得无效。您还需要 template 关键字:

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

    【讨论】:

    • 谢谢!我在发布问题后立即注意到并更正了错误的 using 声明,但你更快!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多