Генерировать switch-case из определений функций во время компиляции - PullRequest
0 голосов
/ 22 января 2020

У меня большой список функций, которые имеют одинаковую сигнатуру параметра:

SKString Login(SKString requestAsJson, const SKAppActionsInterface& appIface)
SKString SimulateUser(SKString requestAsJson, const SKAppActionsInterface& appIface)
SKString ResetSimulatedUser(SKString requestAsJson, const SKAppActionsInterface& appIface)
...

В другой функции я вызываю эти функции в большом операторе switch:

switch (request->Action)
{
case RequestAction::Login:
  return Login(requestAsJson, appIface);
case RequestAction::SimulateUser:
  return SimulateUser(requestAsJson, appIface);
case RequestAction::ResetSimulatedUser:
  return ResetSimulatedUser(requestAsJson, appIface);
...
}

Все в одном и том же файле c ++.

Интересно, смогу ли я как-нибудь автоматически сгенерировать код оператора switch во время компиляции?

Я хотел бы написать какой-нибудь макрос для написания определения функции head:

REQUEST_FUNCTION(Login)
{
  //implementation here
}

, который должен генерировать правильную функцию head (easy), но также добавлять имя к некоторому контейнеру времени компиляции.

Тогда можно было бы выполнить итерацию по контейнеру времени компиляции для генерации различных блоков дел.

Возможно ли это и как? Использование C ++ 11.

1 Ответ

0 голосов
/ 22 января 2020

Этот код не генерирует заголовок функции, но вы можете использовать его для генерации оператора switch:

// List of function names
#define FUNCTIONS_LIST(f) \
    f(Login) \
    f(SimulateUser)

// Generate prototype of each function
#define GENERATE_PROTOTYPE(fname) \
    SKString fname (SKString requestAsJson, const SKAppActionsInterface& appIface);

// Generate switch case of each function
#define GENERATE_SWITCH(fname) \
    case RequestAction:: fname: \
        return fname(requestAsJson, appIface);

// Generate prototypes:
FUNCTIONS_LIST(GENERATE_PROTOTYPE)

// Generate switch:
void f() {
    switch (request->Action)
    {
    FUNCTIONS_LIST(GENERATE_SWITCH)
    }
}

Один из вариантов генерации тел функций - добавить второй аргумент в FUNCTIONS_LIST. Но это совершенно нечитабельно.

#define FUNCTIONS_LIST(f) \
    f(Login, return "yes";) \
    f(SimulateUser, return "no";)

#define GENERATE_BODY(fname, fbody) \
    SKString fname (SKString requestAsJson, const SKAppActionsInterface& appIface) { fbody } 

// Second parameter is unused here
#define GENERATE_SWITCH(fname, fbody) \
    case RequestAction:: fname: \
        return fname(requestAsJson, appIface);

FUNCTIONS_LIST(GENERATE_BODY)
...