#c #lambda #stdmap #std-function
#c #лямбда #stdmap #std-функция
Вопрос:
У меня есть класс Engine, в котором есть элемент типа std::map, который сопоставляет перечисления функциям-членам. Я могу сопоставить перечисление со всеми функциями, если количество аргументов функций одинаково.
enum STATE { OFF, ON, HIBERNATE, RESTART };
enum RETCODE { SUCCESS, FAIL, UNKNOWN, OUTOFBOUND };
class Engine
{
Engine();
RETCODE StateOn(double val);
RETCODE StateOff(double val);
RETCODE StateHibernate(double val);
RETCODE StateRestart(double val);
private:
const std::map<STATE, std::function<RETCODE(double)>> Map_State_FnPtr;
};
Engine::Engine() : Map_State_FnPtr {
{ STATE::ON, [=](double val) {return StateOn(val); } },
{ STATE::OFF, [=](double val) {return StateOff(val); } },
{ STATE::HIBERNATE, [=](double val) {return StateHibernate(val); } },
{ STATE::RESTART, [=](double val) {return StateRestart(val); } }
}
{
// c'tor body
}
Но у меня есть сценарий, в котором некоторые функции могут иметь ноль или несколько аргументов.
Как мне объявить и сконструировать переменную map в таком сценарии?
class Engine
{
Engine();
RETCODE StateOn(); // No arguments
RETCODE StateOff(double val); // 1 argument
RETCODE StateHibernate(double val, const std::string amp; data); // Multiple arguments
RETCODE StateRestart(double val);
private:
const std::unordered_map<STATE, std::function<RETCODE()>> Map_State_FnPtr; // What should be the declaration?
};
Есть другие предложения для этого сценария?
Пожалуйста, помогите.
Ответ №1:
Вы всегда можете игнорировать параметры
{
{ STATE::ON, [=](double, const std::string amp;) {return StateOn(); } },
{ STATE::OFF, [=](double val, const std::string amp;) {return StateOff(val); } },
{ STATE::HIBERNATE, [=](double val, const std::string amp; data) {return StateHibernate(val, data); } },
{ STATE::RESTART, [=](double val, const std::string amp;) {return StateRestart(val); } }
}
Ответ №2:
Как мне объявить и сконструировать переменную map в таком сценарии?
Это невозможно с std::function
. Этот шаблон предлагает определенное количество стираний типов, поскольку он может быть сконструирован с указателями на функции, лямбдами с отслеживанием состояния или указателями на функции-члены, но существует инвариант, то есть сигнатура типа функции, которую вы аппроксимируете с помощью std::function
экземпляра.
Вместо этого вы могли бы определить пользовательский агрегат, который воплощает возможные варианты списков параметров, например
struct StateParams {
double val;
std::string data;
};
затем измените сигнатуры вашей функции на
RETCODE StateOn(const StateParamsamp;);
RETCODE StateHibernate(const StateParamsamp;);
// ...
и std::map
может иметь value_type
std::function<RETCODE(const StatemParamsamp;>
.
Комментарии:
1. Если не с помощью std::function, как я могу объявить / сконструировать std::map в соответствии со следующим требованием. Приветствуются другие альтернативные предложения.
2. Вы могли бы попробовать использовать
std::any
иany_cast
, если у вас есть C 17, но для этого требуется дополнительное поле для запоминания фактической подписи, и это также довольно небезопасно. Простого способа сделать это нет.