How would be resolved this typedef?

I have here a piece of code from a state machine, extracted from https://www.codeproject.com/Articles/1087619/State-Machine-Design-in-Cplusplus


StateMachine.hpp:
 
typedef void (StateMachine::*StateFunc)(EventData *);

How would the below code be written without the above typedef?
1
2
3
4
struct StateStruct 
{
    StateFunc pStateFunc;    
};

Motor.hpp:
1
2
3
4
5
6
7
8
9
10
       const StateStruct * GetStateMap()
     {
        static const StateStruct StateMap[] =
        { { reinterpret_cast<StateFunc>(&Motor::ST_Idle)        }
         ,{ reinterpret_cast<StateFunc>(&Motor::ST_Stop)        }
         ,{ reinterpret_cast<StateFunc>(&Motor::ST_Start)       }
         ,{ reinterpret_cast<StateFunc>(&Motor::ST_ChangeSpeed) } };
        return &StateMap[0];
    }
> How would the below code be written without the above typedef?

1
2
3
4
struct StateStruct
{
    void (StateMachine::*pStateFunc)( EventData* ) ;
};

That seems obvious, but now I get a bunch of errors. Here is what I tried so far:

State_machine.hpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#ifndef STATE_MACHINE_HPP
#define STATE_MACHINE_HPP
 
struct Event_data
{
    virtual ~Event_data() {};
};

struct State_struct;
 
// base class for state machines
class State_machine
{
public:
    State_machine(unsigned char max_states);
    virtual ~State_machine() {}
protected:
    enum { EVENT_IGNORED = 0xFE, CANNOT_HAPPEN };
    unsigned char m_current_state;  // The heart of it all
    void external_event(unsigned char, Event_data* = nullptr);
    void internal_event(unsigned char, Event_data* = nullptr);
    virtual const (State_struct::*p_state_func) * get_state_map() = 0;
private:
    const unsigned char m_max_states;
    bool m_event_generated;
    Event_data* m_p_event_data;
    void state_engine(void);
};

struct State_struct
{
    void (*p_state_func) (Event_data *);
};
  
#endif //STATE_MACHINE_HPP 

Motor.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#ifndef _MOTOR_HPP
#define _MOTOR_HPP
#include "State_machine.hpp"

// structure to hold event data passed into state machine
struct Motor_data : public Event_data
{
    int speed;
};

// the Motor state machine class
class Motor : public State_machine
{
public:
    Motor() : State_machine(ST_MAX_STATES) {}

    // external events taken by this state machine
    void halt();
    void set_speed(Motor_data*);
private:
    // state machine state functions
    void ST_idle(Event_data*);
    void ST_stop(Event_data*);
    void ST_start(Motor_data*);
    void ST_change_speed(Motor_data*);

    // state map to define state function order
public:
     const (State_struct::*p_state_func) * get_state_map()
     {
        static const (State_struct::*p_state_func) state_map[] =
        { { reinterpret_cast<State_struct::*p_state_func>(&Motor::ST_idle)        }
         ,{ reinterpret_cast<State_struct::*p_state_func>(&Motor::ST_stop)        }
         ,{ reinterpret_cast<State_struct::*p_state_func>(&Motor::ST_start)       }
         ,{ reinterpret_cast<State_struct::*p_state_func>(&Motor::ST_change_speed) } };
        return state_map;
    }

    // state enumeration order must match the order of state
    // method entries in the state map
    enum E_states {
        ST_IDLE,  // 0
        ST_STOP,  // 1
        ST_START,  // 2
        ST_CHANGE_SPEED, // 3
        ST_MAX_STATES // 4
    };
};
#endif // _MOTOR_HPP 

When I compile, I get these errors:

g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Motor.d" -MT"src/Motor.o" -o "src/Motor.o" "../src/Motor.cpp"
In file included from ../src/Motor.hpp:3:0,
from ../src/Motor.cpp:2:
../src/State_machine.hpp:22:47: error: ISO C++ forbids declaration of ‘p_state_func’ with no type [-fpermissive]
virtual const (State_struct::*p_state_func) * get_state_map() = 0;
^
../src/State_machine.hpp:22:47: error: ‘p_state_func’ declared as a ‘virtual’ field
../src/State_machine.hpp:22:47: error: expected ‘;’ at end of member declaration
../src/State_machine.hpp:22:69: error: ISO C++ forbids declaration of ‘get_state_map’ with no type [-fpermissive]
virtual const (State_struct::*p_state_func) * get_state_map() = 0;
^
../src/State_machine.hpp:22:51: error: initializer specified for non-virtual method ‘int* State_machine::get_state_map()’
virtual const (State_struct::*p_state_func) * get_state_map() = 0;
^~~~~~~~~~~~~
In file included from ../src/Motor.cpp:2:0:
../src/Motor.hpp:29:40: error: ISO C++ forbids declaration of ‘p_state_func’ with no type [-fpermissive]
const (State_struct::*p_state_func) * get_state_map()
^
../src/Motor.hpp:29:40: error: expected ‘;’ at end of member declaration
../src/Motor.hpp:29:58: error: ISO C++ forbids declaration of ‘get_state_map’ with no type [-fpermissive]
const (State_struct::*p_state_func) * get_state_map()
^
../src/Motor.hpp: In member function ‘int* Motor::get_state_map()’:
../src/Motor.hpp:31:9: error: expected primary-expression before ‘static’
static const (State_struct::*p_state_func) state_map[] =
^~~~~~
../src/Motor.hpp:36:16: error: ‘state_map’ was not declared in this scope
return state_map;
^~~~~~~~~
../src/Motor.hpp:36:16: note: suggested alternative: ‘get_state_map’
return state_map;
^~~~~~~~~
get_state_map
It should compile, with these changes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#ifndef STATE_MACHINE_HPP
#define STATE_MACHINE_HPP

struct Event_data
{
    virtual ~Event_data() {}
};

struct State_struct;

// base class for state machines
class State_machine
{
public:
    State_machine(unsigned char max_states);
    virtual ~State_machine() {}

protected:
    enum { EVENT_IGNORED = 0xFE, CANNOT_HAPPEN };
    unsigned char m_current_state;  // The heart of it all
    void external_event(unsigned char, Event_data* = nullptr);
    void internal_event(unsigned char, Event_data* = nullptr);
    virtual const State_struct* get_state_map() = 0;
private:
    const unsigned char m_max_states;
    bool m_event_generated;
    Event_data* m_p_event_data;
    void state_engine(void);
};

struct State_struct
{
    void (State_machine::*p_state_func) (Event_data *);
};

#endif //STATE_MACHINE_HPP

#ifndef _MOTOR_HPP
#define _MOTOR_HPP
// #include "State_machine.hpp"

// structure to hold event data passed into state machine
struct Motor_data : public Event_data
{
    int speed;
};

// the Motor state machine class
class Motor : public State_machine
{
public:
    Motor() : State_machine(ST_MAX_STATES) {}

    // external events taken by this state machine
    void halt();
    void set_speed(Motor_data*);
private:
    // state machine state functions
    void ST_idle(Event_data*);
    void ST_stop(Event_data*);
    void ST_start(Motor_data*);
    void ST_change_speed(Motor_data*);

    // state map to define state function order
public:
     const State_struct* get_state_map()
     {
        static const State_struct state_map[] =
        {
          { reinterpret_cast< decltype(State_struct::p_state_func) >( &Motor::ST_idle ) },
          { reinterpret_cast< decltype(State_struct::p_state_func) >( &Motor::ST_stop ) },
          { reinterpret_cast< decltype(State_struct::p_state_func) >( &Motor::ST_start ) },
          { reinterpret_cast< decltype(State_struct::p_state_func) >( &Motor::ST_change_speed ) }
        };

        return state_map;
    }

    // state enumeration order must match the order of state
    // method entries in the state map
    enum E_states {
        ST_IDLE,  // 0
        ST_STOP,  // 1
        ST_START,  // 2
        ST_CHANGE_SPEED, // 3
        ST_MAX_STATES // 4
    };
};
#endif // _MOTOR_HPP 

http://coliru.stacked-crooked.com/a/71cb6e26a57ccc60

Don't know where you got this code from; but note that using the results of the reinterpret casts to call the functions would engender undefined behaviour.
First, I thank you for your 'repairing', I fiddled at the code a more than a half day long.

Don't know where you got this code from; but note that using the results of the reinterpret casts to call the functions would engender undefined behaviour.

What would you suggest for improving, e.g avoiding the reinterpret_cast?
Topic archived. No new replies allowed.