0

我正在尝试使用最终状态机和 std::variant<..>

std::variant 将保存所有可能的状态状态将在 State 类中定义。

我想要的是有一个 BaseState 类,应该在其中处理“通用事件”。使用派生的 State 类处理特定的状态。

struct LightOn;
struct LightOff;

struct Toggle;
struct Reset;

using State = std::variant<LightOn,LightOff>;
using Event = std::variant<Toggle,Reset>;

struct BaseState
{
    void on_enter(){Serial.printf("BaseState enter\r\n");};
    void on_event (const Reset &r);
};

struct LightOn : BaseState
{
    LightOn(){Serial.printf("LightOn constructor\r\n");};
    void on_event(const Event &e);
    void on_exit(){Serial.printf("LightOn exit\r\n");}
    void on_enter(){Serial.printf("LightOn enter\r\n");}
};

struct LightOff : BaseState
{
    LightOff(){Serial.printf("LightOff constructor\r\n");};
    void on_event(const Event &e);
    void on_exit(){Serial.printf("LightOff exit\r\n");}
};

struct Toggle
{
    Toggle(){Serial.printf("Struct Toggle\r\n");};
};

struct Reset
{
    Reset(){Serial.printf("Struct Reset\r\n");};
};

void LightOn::on_event(const Event &e){Serial.printf("LightOn event\r\n");};
void LightOff::on_event(const Event &e){Serial.printf("LightOff event\r\n");};
void BaseState::on_event(const Reset &r){Serial.printf("BaseState reset\r\n");};

我的问题在于on_event功能。

Basestate中的 Reset 有一个特定的,void on_event(const Reset &r); 而 LightOn 和 LightOff 中有一个更通用的void on_event(const Event &e);(使用 Event = std::variant<Toggle,Reset>;)

但是当我这样做时

LightOn n;
n.on_event(Reset{}); 

来自 LightOn 的 on_event 被调用,而不是来自 BaseState 的那个。

有没有办法实现:当 BaseState 函数可用于此特定事件时调用 BaseState 函数?

4

1 回答 1

1

在这个问题中回答了类似的事情。

名称查找在子类处停止(因为那里有匹配项)。

您可以使用using将基类 ( BaseState) 中的函数引入同一范围。(这将使它遵循通常的重载规则,在这种情况下选择完全匹配,这是来自基类的函数。)

struct LightOn;
struct LightOff;

struct Toggle;
struct Reset;

using State = std::variant<LightOn,LightOff>;
using Event = std::variant<Toggle,Reset>;

struct BaseState
{
    void on_enter(){Serial.printf("BaseState enter\r\n");};
    void on_event (const Reset &r);
};

struct LightOn : public BaseState
{
    LightOn(){Serial.printf("LightOn constructor\r\n");};
    using BaseState::on_event; // <-- Added to the scope
    void on_event(const Event &e); 
    void on_exit(){Serial.printf("LightOn exit\r\n");}
    void on_enter(){Serial.printf("LightOn enter\r\n");}
};

struct LightOff : public BaseState
{
    LightOff(){Serial.printf("LightOff constructor\r\n");};
    void on_event(const Event &e);
    void on_exit(){Serial.printf("LightOff exit\r\n");}
};

struct Toggle
{
    Toggle(){Serial.printf("Struct Toggle\r\n");};
};

struct Reset
{
    Reset(){Serial.printf("Struct Reset\r\n");};
};

void LightOn::on_event(const Event &e){Serial.printf("LightOn event\r\n");};
void LightOff::on_event(const Event &e){Serial.printf("LightOff event\r\n");};
void BaseState::on_event(const Reset &r){Serial.printf("BaseState reset\r\n");};

另外,请查看Boost 编译时 FSM 生成器示例。它似乎实现了与您相同的目标。

于 2020-07-04T11:33:31.070 回答