Search code examples
c++castingfunction-pointerscompiler-warningsstate-machine

Implementig a C++ State Machine. How to solve Wpmf-convesion Warning?


I am trying to implement in C ++, the state machine described in this link for C language: https://barrgroup.com/Embedded-Systems/How-To/Coding-State-Machines.

I have created an Fsm class, which implements the behavior of the state machine, and a Machine class, whose methods will be the states.

The code works, but it generates a warning (-Wpmf-conversions) when I try to save the memory address of a Machine method, in State state__

class Fsm
{
public:
    typedef void (*State)();
private:
    State state__;
public:
    Fsm(State state);
    void dispatch();
}; 

Fsm::Fsm(State state)
{
    state__ = state ;
} //Fsm

void Fsm::dispatch()
{
    (*state__)() ;
}



class Machine : public Fsm
{
public:
    Machine() : Fsm((State)&Machine::initial) {}       // ctor
}; 

I expect to solve the -Wpmf-conversions warning.


Solution

  • State does correspond to a function pointer.

    Unfortunately, you have not provided a definition for initial in your code. So it's a little guess. But in your constructor's argument (State)&Machine::initial you seem to assume it's a static member function.

    This compiles without errors or warnings:

    class Machine : public Fsm
    {
        static void initial();    // make sure it's static 
    public:
        Machine() : Fsm((State)&Machine::initial) {}       // ctor
    }; 
    

    Now if you want a pointer to a member function, it's another story. First, you'd need to define State accordingly:

    typedef void (Fsm::*State)();
    

    Then the dispatch must invoke a member function:

    void Fsm::dispatch()
    {
        (this->*state__)() ;
    }
    

    The only issue could be that you call a derived member function pointer by using a base member function pointer. Fortunately, this is guaranteed to work, as explained in this excellent answer.