Designing simple state machine in C++ I have designed a simple state machine for the following diagram:



I am seeking improvements from the community. I especially don't like two things:


When calling performAction I wan't to send only the action without the callback.
And maybe remove the Action enum from the Engine class.


For simplicity everything is added in one .cpp file:

#include &lt;iostream&gt;
#include &lt;utility&gt;
#include &lt;map&gt;

typedef enum {
    Idle,
    Start,
    Stop,
    ChangeSpeed
}State;


class Engine
{
public:
    typedef enum {
        SetSpeed,
        Halt
    }Action;

    typedef void (Engine::*DoAction)(void);

    Engine() {
        std::cout &lt;&lt; "Engine()" &lt;&lt; std::endl;
    }
    void setSpeed() {
        std::cout &lt;&lt; "Engine::setSpeed()" &lt;&lt; std::endl;
    }
    void halt() {
        std::cout &lt;&lt; "Engine::halt()" &lt;&lt; std::endl;
    }
};

struct ActionCallback
{
    Engine::Action         action;
    Engine::DoAction       callback;
    ActionCallback(Engine::Action a, Engine::DoAction c):action(a), callback(c){}
};

struct StateAction {
    State state_;
    Engine::Action action_;
    StateAction(State state, Engine::Action action):state_(state), action_(action){}
    friend bool operator&lt;(const StateAction&amp; sta1, const StateAction&amp; sta2) {
        return (sta1.state_ &lt; sta2.state_) ||
        (sta1.state_ == sta2.state_ &amp;&amp;
         sta1.action_ &lt; sta2.action_);
    }
};

class StateMachine {
public:
    typedef std::map&lt;StateAction, State&gt; StateDiagram;


    StateMachine(Engine &amp;engine):engine_(engine) {
        stateDiag_[StateAction(Idle, Engine::SetSpeed)] = Start;
        stateDiag_[StateAction(Start, Engine::SetSpeed)] = ChangeSpeed;
        stateDiag_[StateAction(ChangeSpeed, Engine::SetSpeed)] = ChangeSpeed;
        stateDiag_[StateAction(ChangeSpeed, Engine::Halt)] = Stop;
        stateDiag_[StateAction(Start, Engine::Halt)] = Stop;
        //
        //  current state is initialized to Idle
        //
        currentState_ = Idle;
        std::cout &lt;&lt; "State machine initial state: " &lt;&lt; currentState_ &lt;&lt; std::endl;
    }
    void performAction(ActionCallback actionCallback) {
        //
        //  The state machine "state" is: currentState
        //
        StateAction stateAction(currentState_, actionCallback.action);

        if (stateDiag_.find(stateAction) == stateDiag_.end()) {
            //
            //  Invalid state transition
            //
            std::cout &lt;&lt; "You cannot perform action: "
            &lt;&lt; actionCallback.action
            &lt;&lt; " from state: "
            &lt;&lt; currentState_
            &lt;&lt; ", invalid transition!!!"
            &lt;&lt; std::endl;
            return;
        }
        State oldState = currentState_;
        //
        //  Execute the action and update the state machine
        //
        (engine_.*actionCallback.callback)();
        currentState_ = stateDiag_[stateAction];

        std::cout &lt;&lt; "State changed:\n\tOld state: " &lt;&lt; oldState &lt;&lt; "\n\tNew state: " &lt;&lt; currentState_ &lt;&lt; std::endl;
        //
        //  If current state is: Stop change state to: Idle
        //
        if (Stop == currentState_) {
            oldState = currentState_;
            currentState_ = Idle;
            std::cout &lt;&lt; "State changed:\n\tOld state: " &lt;&lt; oldState &lt;&lt; "\n\tNew state: " &lt;&lt; currentState_ &lt;&lt; std::endl;
        }


    }
    State getInitialState() {
        return Idle;
    }

private:
    StateDiagram stateDiag_;
    State currentState_;
    Engine engine_;
};
int main()
{
    Engine engine;
    StateMachine stateMachine(engine);
    stateMachine.performAction(ActionCallback(Engine::SetSpeed, &amp;Engine::setSpeed));
    stateMachine.performAction(ActionCallback(Engine::Halt, &amp;Engine::halt));
    stateMachine.performAction(ActionCallback(Engine::Halt, &amp;Engine::halt));
    return 0;
}
That's typically how C enums are written, but it's done differently in C++.  The typedef keyword is no longer needed, and the name is given after the enum keyword.

enum State {
    Idle,
    Start,
    Stop,
    ChangeSpeed
};