当需要特定参数时,std::map中的成员方法如何使用?

How can a member method in an std::map when I want specific parameters

本文关键字:map 何使用 成员方法 std 参数      更新时间:2023-10-16

我正在尝试使用包含动作的映射构建fsm。我试图将下一个状态绑定到动作,但它似乎不像预期的那样工作。下面是一个简单的例子:

我有一个枚举,这个fsm将使用的所有状态:

typedef enum
{
    init,
    query,
    anotherState
} State;

我有一个包含我的动作方法的类。

class MyClass
{   
    protected:
    void BuildStateMap();
    void StateEngine();
    private:
    void Init(State nextState);
    void Query(State nextState);
    State state;
    std::map<State, std::function<void(State)>> stateMap;

我有一个构建状态图的方法。

MyClass::BuildStateMap()
{
    state = init;
    map[init] = std::bind(&MyClass::Init, this, query);
    map[query] = std::bind(&MyClass::Query, this, anotherState);
    ...
}

操作的实现可能如下所示:

void MyClass::Init(State nextState)
{
    DoStuff();
    state = nextState;
}

StateEngine的实现可能是这样的:

void MyClass::StateEngine()
{
    auto itr = stateMap.find(state);
    if (itr != stateMap.end())
    {
        itr->second();  // I think this should call Init() with the parameter query that was "bound" to it in the std::bind call above.
    }
}

那么为什么当我调用itr->second();我是否得到这样的错误:

no match for call to '(std::function<void(State)>)()' 

,当我期望它自动将状态查询作为参数传递时。

谢谢,克里斯。

由于在绑定本身中包含了State参数的值,因此映射应该是类型为std::function<void()>的。

如果你想在调用时传递State而不是绑定时,那么你可以让地图保持原样,但你需要使用itr->second(whateverStateShouldBePassed)。这还需要您将绑定设置为std::bind(&MyClass::Init, this, std::placeholders::_1)

请注意,在这种情况下,lambdas通常提供比bind更方便的语法,尽管这在很大程度上是一个品味问题:

stateMap<State, std::function<void()>> map;
map[init] = [=]() { Init(query); };