代码之家  ›  专栏  ›  技术社区  ›  francesco

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

  •  1
  • francesco  · 技术社区  · 7 年前

    让我考虑一个从基本模板类派生的模板类。基类包含模板成员。在这种情况下,通常可以使用指针从派生类访问基类的成员 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 类尝试访问模板函数 增量 从基部继承的。使用指针 如上面的注释行所示

    this->increment<1>();
    

    给出编译错误

    expected primary-expression before ‘)’ token
    

    在尝试了一段时间之后,我发现可以像上面的代码一样,访问 增量 通过scope运算符执行功能

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

    然而,它显式地实例化了 基础 具有 T=int 是的。如果我想打电话给 增量 继承的成员 base<T> ,具有泛型 T 分类为

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

    我得到的错误和上面一样。

    我正在使用GCC 8.1.1

    问题是:为什么使用指针 编译器无法解析继承的成员函数 增量 是吗?如何实例化继承的模板函数 增量 ,从继承的类 基础 是吗?

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

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

    2 回复  |  直到 7 年前
        1
  •  1
  •   Miles Budnek    7 年前

    打电话 this->increment<1>() 无效,因为 increment 是一个依赖函数模板。因此,您需要使用 template 关键词

    this->template increment<1>();
    

    你的 using 指令和 base<int>::increment<1>() 呼叫也不正确。如果 deriv 与其他类型无关 int 这两个都不行。你应该用 T 而不是 内景 在这两种情况下。当这样做的时候 base<T>::increment<1>() 将因同样原因而失效 此->增量<1>() 无效。你需要 模板 这里还有关键词:

    base<T>::template increment<1>();
    
        2
  •  3
  •   An0num0us parreirat    7 年前

    除非您另外指定,否则编译器假定您访问的名称不是模板,因此 < > 分别标记为小于和大于符号(行被解析为 ((this->increment)<1)>() )中。这是因为 this base<T> 都依赖于模板参数 T 编译器无法查找 increment 看看它是不是一个模板。对于操作符左边的名称依赖于任何模板参数,右边的名称是模板ID(名称为 <> )中。要解决这个问题,您需要使用 template 关键词

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

    为什么 base<int>::increment<1>(); 那么编译呢?因为它不依赖于 T (指已知的专门化),因此名称 增量 可以查找以确定它是否是模板。
    但如果 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 不是静态的,而是附加的变化)。