在模板类函数定义中使用“ this”指针-表达式必须具有(pointer-to-)函数类型

时间:2018-12-31 18:09:26

标签: c++ templates inheritance this

我有一个模板化的基类,用作伪状态机类型的对象。它有一个主要方法if not x(在错误检查之后)逐步检查一个枚举(作为模板参数之一提供),并针对其处于任何状态运行一个处理程序。问题是我必须使用该指针引用Progress_State()数组,该数组是派生类函数指针的数组(即Event_Handler = Event_Handlers[i])。

函数定义在一个单独的XX.cpp文件中,该文件包括XX.h文件(定义了模板类)。但是,由于所有函数都是模板函数,因此我最终得到了未解析的符号。经过研究,我发现编译使用模板类的文件时,编译器需要访问模板化函数定义,因此我将XX.cpp重命名为XX.tpp,并在#include“ XX .tpp”位于“ XX.h”底部。它以前没有任何问题地进行过编译,但是只是这一更改导致了编译错误。最值得注意的是,在尝试调用存储的函数指针的行中,出现“表达式必须具有指针类型”错误。

Templates.h

Derived_Class::*

Templates.tpp

/*
 * derived_class = is the derived class type, used for correctly 
 * using the function pointers
 * event_type = the enum that we're using as "sequencer"
 * max_events = the "max_XX" enum, used to set our handler array size
 */
template< derived_class, event_type, max_events >
Class Base{

// Set up the typedef for the derived class function pointer
   typedef int(derived_class::*PFN)(void);

public:
    // ....
   int Progress_State();
    // ....

private:
   // ....
   PFN           Event_Handlers[Num_Events];
   event_type    Current_State;
   // ....       

};

// Bring in the templated function definitions
#include "Templates.tpp"

我怀疑这种情况正在发生,因为“ this”指针实际上指向某种派生类,但是我找不到解决它的方法。

以下是我尝试过的其他操作:

以下几行会产生以下错误:

template< derived_class, event_type, max_events >
int Base::Progress_State(){

   // Various error checking stuff, including whether or not we're
   // at the end of the sequence, or if we have a null handler

   // If no errors, continue.
   // FYI: 0 indicates no errors

   if( 0 == this->*Event_Handlers[Current_State]() ){ // <--* error happens here

      // Step sequence -- some funkiness here to allow for incrementing
      // of the sequence without overloading the ++ operator for every
      // enum we intend to track, while also protecting against 
      // overruns

      Current_State = static_cast<event_type>( 
          (static_cast<int>(Current_Event) + 1) % max_events
       );
   }

   // ... do other stuff as needed ...
}
  

错误:“表达式必须具有(指向指针的)功能

预期的功能是仅调用注册的处理函数(单独设置)并逐步执行该顺序。

预先感谢

2 个答案:

答案 0 :(得分:1)

我在您的代码中看到以下问题:

您尝试使用this(不是兼容的指针类型)在基类中调用派生类的成员函数。首先必须转换为派生类的指针类型。您“知道”这是派生类的指针,因为您在此处使用CRTP模式。 https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

通过一个简化的示例,调用类似于:

template < typename Derived >
class Base
{
    public:
        using PTR_T = void(Derived::*)();
        PTR_T ptr;

        Base( PTR_T _ptr ) : ptr {_ptr}{}

        void Call()
        { 
        // the important thing here is the cast to the derived type of "this"
            (((Derived*)this)->*ptr) ();
        }
};

class Derived: public Base< Derived >
{
    public:
        void F() { std::cout << "Hello" << std::endl; }

        Derived():Base{ &Derived::F } {}
};  

int main()
{   
    Derived d;
    d.Call();
}

答案 1 :(得分:0)

您似乎正在搜索std::invoke。这是MSVC已经使用了一段时间处理可调用对象的功能。 (_INVOKE在标准中可用)。

 auto return value = std::invoke(func, arg1, arg2, ...);

对于您的情况,您可以这样称呼它:

 auto errorCode = std::invoke(EventHandlers[Current_State], *this);