Существует разница между типом void(*)(int)
(который вы называете Actions::DoAction
) и типом void(Device::*)(int)
, который &Device::TakeControl
и т. Д.
Обратите внимание, что вам нужно и a Device
и int
для вызова последнего. К счастью, вы можете настроить ActionCallback
, чтобы использовать это.
struct ActionCallback
{
using DeviceCall = void(Device::*)(Actions::Action);
Actions::Action action = Actions::action1;
DeviceCall callback = &Device::NoAction;
void operator()(Device * device) { (device.*callback)(action); }
};
Мы определили operator()
, поэтому экземпляр ActionCallback
можно вызвать, как если бы это была функция
struct StateMachine {
using StateMachineMap = std::map<std::pair<int, int>, ActionCallback>;
StateMachineMap m_stateMachineMap;
StateMachine() {
m_stateMachineMap[std::make_pair(1, 2)] = ActionCallback{Actions::Action::action1, &Device::Start};
m_stateMachineMap[std::make_pair(1, 3)] = ActionCallback{Actions::Action::action2, &Device::Stop};
m_stateMachineMap[std::make_pair(1, 4)] = ActionCallback{Actions::Action::action3, &Device::Start};
m_stateMachineMap[std::make_pair(1, 5)] = ActionCallback{Actions::Action::action3, &Device::Stop};
m_stateMachineMap[std::make_pair(1, 6)] = ActionCallback{Actions::Action::action2, &Device::Start};
m_stateMachineMap[std::make_pair(1, 7)] = ActionCallback{Actions::Action::action1, &Device::NoAction};
}
void performAction(std::pair<int, int> what, Device * who) {
m_stateMachineMap[what](who);
}
};
Также существует тип, который обобщает любой вызываемый объект с данной сигнатурой, std::function
.
Если Actions::Action
передать с Device *
, вы можете использовать
using ActionCallback = std::function<void(Device *, Actions::Action)>;
StateMachineMap m_stateMachineMap { { std::make_pair(1, 2), &Device::Start } };
Однако вы хотите связать определенный Action
с обратным вызовом. Лямбда может захватывать значения для использования при вызове.
using DeviceCall = void(Device::*)(Actions::Action);
using ActionCallback = std::function<void(Device *)>;
ActionCallback make_action_callback(Actions::Action action, DeviceCall callback)
{
return [=](Device * device){ (device.*callback)(action); };
}
StateMachineMap m_stateMachineMap { { std::make_pair(1, 2), make_action_callback(Actions::action1, &Device::Start) } };