This question already has answers here:
Why doesn't a derived template class have access to a base template class' identifiers?

(4个答案)


4年前关闭。




我想编译一个C++软件,该软件可以给我一些编译
错误。此错误与无法解决的成员函数有关。

这个问题应包含回答该问题所需的一切。但是,如果那
确实是这样,我现在应该已经找到答案了。所以请放心
浏览sourcecode
此问题中的所有代码都不属于我的,而是根据GPLv2许可的。

我编译的系统是运行Red Hat Enterprise Server的IBM PowerPC 740
6.8。使用模块,我启用了Clang 3.7。一切都可以交叉编译
对于IBM PowerPC A2芯片,它是一台IBM BlueGene / Q super 计算机。那些事
应该由我的compilationscript照顾
设置所需的许多configureCXXFLAGS

我当前在当前状态下遇到的编译错误(提交fee0a02)是这样的:
bfmcommqmp.C:183:5: error: use of undeclared identifier 'gather'
    gather(result_cb, psi, dag);
    ^

令人讨厌的行在bfmcommqmp.C中的此方法定义中:
168 template <class Float>
169 void bfmcommQMP<Float>::comm_start(int result_cb, Fermion_t psi, int dag) {
170     // gather the faces. Routines here are threaded.
171     // All threads cooperate in gathering.
172
173     //  if ( this->isBoss() && (me == 0)) {
174     //    this->Error("comm_start checking heap\n"); fflush(stdout);
175     //    mcheck_check_all();
176     //    this->Error("comm_start mcheck_all");fflush(stdout);
177     //  }
178
179     int me = this->thread_barrier();
180
181     this->thread_barrier();
182
183     gather(result_cb, psi, dag);
184
185     this->thread_barrier();
186     if (me == 0) {
187         comm_qmp_start(psi);
188     }
189     this->thread_barrier();
190
191     return;
192 }

这当然是bfmcommQMP类的一部分。看相关
头文件bfmcommqmp.h,找到了这个类声明:
  8 template <class Float>
  9 class bfmcommQMP : public bfmbase<Float> {
 10   public:
 11     // QMP thingy-me-bob's
 12     QMP_msghandle_t multi_handle[2];
 13
 14     QMP_msgmem_t send_ops_msgmem_t[8];
 15     QMP_msgmem_t recv_ops_msgmem_t[8];
 16
 17     QMP_msghandle_t send_multi_handle;
 18     QMP_msghandle_t send_handles[8];
 19
 20     QMP_msghandle_t recv_handles[8];
 21     QMP_msghandle_t all_handles;
 22
 23     Float *simd_rbuf[8];
 24     Float *receive_area;
 25
 26     int num_op;
 27
 28     virtual bool isBoss();
 29
 30     virtual void recv_init(void);
 31     virtual void recv_end(void);
 32
 33     virtual void comm_init(void);
 34     virtual void comm_end(void);
 35     virtual void comm(int result_cb, Fermion_t psi, int dag);
 36     virtual void comm_start(int result_cb, Fermion_t psi, int dag);
 37     virtual void comm_qmp_start(Fermion_t psi);
 38     virtual void comm_qmp_complete(void);
 39     virtual void comm_merge(void);
 40     virtual void comm_complete(int result_cb, Fermion_t psi);
 41     virtual void comm_gsum(double &val);
 42     virtual void comm_gsum(double *val, int N);
 43 };

它继承自bfmbase。跳至bfm.h文件,该文件包含在bfmcommqmp.h,我们找到了类定义,其中包含两个gather方法:
 133 template <class Float>
 134 class bfmbase : public bfmarg, public ThreadModel {
 135   public:

 282     void gather(int result_cb, Fermion_t psi, int dag);
 283     void gather(int mu, int result_cb, Fermion_t psi, int dag);

1018 };

据我了解,类bfmcommQMP应该继承了gather中的非虚拟函数bfmbase。显然不是这样,
否则Clang不会对此抱怨。

我在这里想念什么?为什么gather函数在内部无法使用bfmcommQMP::comm_start成员函数?

最佳答案

问题在于您的派生类是dependent name。您需要用gather()限定对基类中this->gather()的调用,否则编译器不会从基类中解析gather()。为了简化,

template<class T> struct Base
{
    void f();
};

template<class T> struct Derived: Base<T> // dependent name
{
    void foo()
    {
        this->f(); // won't compile without this->
    }
};

另一种方法是
using Base::f;

用派生的Derived::foo()或像这样限定通话
Base::f();

相关:Why do I have to access template base class members through the this pointer?

10-06 12:42