提问者:小点点

使用std::variant<…>时调用BaseState函数而不是派生函数


我正在试验finate状态机和std::variant<..>;

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

我想要的是有一个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 : 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函数中。

在basestevoid on_event(const Reset&r);中有一个关于Reset的特定选项,在LightOn和LightOffvoid on_event(const Event&e);中有一个更通用的选项(使用Event=std::variant)

但当我这么做的时候

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

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

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


共1个答案

匿名用户

这个问题也回答了类似的问题。

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

您可以使用using将函数从基类(baseSteat)引入到相同的作用域中。 (这将使它遵循通常的重载规则,在本例中选择精确的匹配项,即来自基类的函数。)

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生成器示例。 它似乎和你完成了同样的目标。