C ++ лямбды и затворы - PullRequest
       14

C ++ лямбды и затворы

0 голосов
/ 27 августа 2018

Я заменяю ... около 6000 строк кода десериализации C на то, что, я надеюсь, составляет около 3000 строк C ++. Основной существующий шаблон выглядит так:

ser_ret_t msgpack_unpack_mystruct(msgpack_object *obj, mystruct_t *d, void *unused = NULL)
{
  NEXT_WORK_OBJ(array, i, work_obj);
  ret |= msgpack_unpack_line(work_obj, &d->line);
  NEXT_WORK_OBJ(array, i, work_obj);
  ret |= msgpack_unpack_node(work_obj, &d->leftNode);
  //etc....

Это повторяется один раз для каждой переменной в данной структуре. array, i и work_obj - все переменные состояния, используемые msgpack, а d - указатель произвольной структуры. NEXT_WORK_OBJ - макрос препроцессора, необходимый для настройки переменных состояния. msgpack_unpack_* - это функция с произвольными параметрами.

Это не только многословно, но и неполно, поскольку базовый буфер продолжает обрабатываться даже в случае сбоя.

Моя мысль состоит в том, чтобы заменить переменные состояния классом состояния / помощника, при этом единственной проблемой является вызов произвольной функции внутри класса. Я справляюсь с этим, делая не вызов внутри класса, а через лямбду.

class UnpackHelper
{
public:
  void GetNext(std::function<ser_ret_t(msgpack_object*)> callback)
  {
    //make sure it's safe to continue processing buffer.
    if (m_status != SER_SUCCESS)
      return;
    NextObj();
    m_status |= callback(m_pWork);
  }
};

NextObj() заменяет макрос препроцессора и корректирует внутренние переменные состояния класса. Теперь код клиента выглядит так:

ser_ret_t msgpack_unpack_mystruct(msgpack_object *obj, mystruct_t *d, void *unused = NULL)
{
  UnpackHelper up;
  up.GetNext([=](auto pWork) {return msgpack_unpack_line(pWork, &d->line); });
  up.GetNext([=](auto pWork) {return msgpack_unpack_node(pWork, &d->leftNode);});

Мой вопрос конкретно о клиентском коде и лямбдах. Насколько я понимаю, здесь происходит default capture, и я также понимаю, что это не рекомендуется. Поскольку захват всегда происходит на элементе указателя, переданного в функцию (d), тем не менее, Я считаю, что этот шаблон безопасен. Это правильно? Учитывая тысячи лямбд, которые будут существовать, я бы хотел избежать ненужного многословия. Во-вторых, можно ли каким-либо образом сократить или удалить список параметров? (auto pWork) довольно минимально, но ...

Мой новый, третий вопрос, основанный на изучении std::function .. мой механизм обратного вызова вообще необходим? std::function выглядит как то, что я мог бы использовать, чтобы создать произвольный вызов непосредственно в классе. В настоящее время я смотрю на принятый ответ здесь: C ++: передать функцию с произвольным числом параметров в качестве параметра , чтобы посмотреть, можно ли ее применить к моему коду ... без использования переменных аргументов в стиле C. Похоже, это может сработать, но ничего не покупает, кроме раздувания кода, вызванного расширением шаблона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...