使用可变参数模板重载的状态机

statemachine using variadic template overloading

我正在尝试使用可变参数模板在 C++ 中构建一个状态机。

class Event {};

template<typename... TEvents>
class StateMachineActionHandler
{
public:
    void action() = delete;
};

template<typename TEvent, typename... TEventRest>
class StateMachineActionHandler<TEvent, TEventRest...> : public StateMachineActionHandler<TEventRest...>
{
public:
    virtual void action(const TEvent& event)
    {
        std::cout << "default" << std::endl;
    }
    using StateMachineActionHandler<TEventRest...>::action;
};

template <class ...TEvents>
class State : public StateMachineActionHandler<TEvents...>
{
public:
    virtual void enterAction() = 0;
    virtual void exitAction() = 0;
};


template <class ...TStates>
class StateMachine
{
public:
    StateMachine()
    {
        m_cur = std::get<0>(m_states);
        std::visit([](auto state){state.enterAction();}, m_cur);
    }

    virtual ~StateMachine() = default;

    template<typename TEvent>
    void handleEvent(const TEvent& event)
    {
        std::visit([&event] (auto state){ state.action(event);}, m_cur);
    }

private:
    std::tuple<TStates...> m_states;
    std::variant<TStates...> m_cur;
};

然后我创建一个 class 来实现这个状态机。但是,对于 StateA,我没有覆盖函数 void action(const EventB& event),因为我希望它具有模板中提供的空默认实现。

class EventA : public Event {};
class EventB : public Event {};

class StateA : public State<EventA, EventB>
{
public:
    void action(const EventA& event) override { std::cout << "new A A" << std::endl;}

    void enterAction() override {std::cout << "enter A" << std::endl; }
    void exitAction() override {std::cout << "exit A" << std::endl; }
};

class StateB : public State<EventA, EventB>
{
public:
    void action(const EventA& event) override { std::cout << "new B A" << std::endl;}
    void action(const EventB& event) override { std::cout << "new B B" << std::endl;}

    void enterAction() override {std::cout << "enter B" << std::endl; }
    void exitAction() override {std::cout << "exit B" << std::endl; }
};

class StateC : public State<EventA, EventB>
{
public:
    void action(const EventA& event) override { std::cout << "new C A" << std::endl;}
    void action(const EventB& event) override { std::cout << "new C B" << std::endl;}

    void enterAction() override {std::cout << "enter C" << std::endl; }
    void exitAction() override {std::cout << "exit C" << std::endl; }
};

class StateMachineTest : public StateMachine<StateA, StateB, StateC>
{
};

现在如果我使用这个 class 我会得到一个编译错误:

int main()
{
    StateMachineTest testSM;
    EventB eventB;
    testSM.handleEvent(eventB);
}

error: cannot convert ‘const EventB’ to ‘const EventA&’

为什么它看不到空的默认实现?

您需要使用 using 声明将默认实现引入派生的 class 定义

class StateA : public State<EventA, EventB>
{
public:
    using State<EventA, EventB>::action;
    void action(const EventA& event) override { std::cout << "new A A" << std::endl;}

    void enterAction() override {std::cout << "enter A" << std::endl; }
    void exitAction() override {std::cout << "exit A" << std::endl; }
};

Demo