Как иметь ноль или более аргументов для std :: function, используемой в качестве значения в std :: map? - PullRequest
2 голосов
/ 27 марта 2019

У меня есть класс 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
}

Но у меня есть сценарий, в котором некоторые функции могут иметь ноль или несколько аргументов. Как мне объявить и построить переменную карты в таком сценарии?

class Engine
{
    Engine();
    RETCODE StateOn();                                              // No arguments
    RETCODE StateOff(double val);                                   // 1 argument
    RETCODE StateHibernate(double val, const std::string & data);   // Multiple arguments
    RETCODE StateRestart(double val);
private:
    const std::unordered_map<STATE, std::function<RETCODE()>> Map_State_FnPtr; // What should be the declaration?
};

Есть ли другие предложения по этому сценарию? Пожалуйста, помогите.

Ответы [ 2 ]

2 голосов
/ 27 марта 2019

Вы всегда можете игнорировать параметры

{
    { STATE::ON, [=](double, const std::string &) {return StateOn(); } },
    { STATE::OFF, [=](double val, const std::string &) {return StateOff(val); } },
    { STATE::HIBERNATE, [=](double val, const std::string & data) {return StateHibernate(val, data); } },
    { STATE::RESTART, [=](double val, const std::string &) {return StateRestart(val); } }
}
2 голосов
/ 27 марта 2019

Как мне объявить и построить переменную карты в таком сценарии?

Это невозможно с std::function. Этот шаблон предлагает определенное количество типов стирания, так как он может быть создан с помощью указателей функций, лямбд с сохранением состояния или указателя на функции-члены, но есть инвариант, т. Е. Сигнатура типа функции, которую вы аппроксимируете с экземпляром std::function .

Вместо этого вы можете определить пользовательский агрегат, который воплощает возможные варианты списков параметров, например,

struct StateParams {
    double val;
    std::string data;
};

затем измените сигнатуры вашей функции на

RETCODE StateOn(const StateParams&);
RETCODE StateHibernate(const StateParams&);
// ...

и std::map может иметь value_type std::function<RETCODE(const StatemParams&>.

...