Как обрабатывать лямбды в пред-лямбда-компиляторе - PullRequest
5 голосов
/ 03 ноября 2011

У меня есть некоторый код, который можно значительно уменьшить по сложности с помощью лямбды.Однако, к сожалению, мы должны использовать компилятор, который не полностью поддерживает C ++ 11, и мы не можем легко переключаться.Теперь вопрос заключается в том, как сохранить логику как можно ближе к лямбда-выражению с недоступными функциями (т. Е. Доступны std::function, лямбды нет).

Обычное решение - определить где-то функтореще, а затем используйте его в соответствующем месте:

struct functor{
   functor( type & member ) : m_member( member ) {}
   void operator()( ... ) {...}
   type & m_member;
};

void function() {
   use_functor( functor(...) );
}

Я очень привык к этому шаблону, хотя мне он очень не нравится.Основная причина не определения класса обычно заключается в том, что функтор будет использоваться в STL, а шаблоны не похожи на структуры, определенные внутри функции.Однако в моем случае функция use_functor() будет нормальным методом, поэтому я могу определить функтор внутри самой функции (каждый функтор используется только в одной функции).

void function() {
   struct functor{
      functor( type & member ) : m_member( member ) {}
      void operator()( ... ) {...}
      type & m_member;
   };
   use_functor( functor(...) );
}

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

void function() {
   struct{
      // functor( type member ) : m_member( member ) {}
      void operator()( ... ) {...}
      // type & m_member;
   } callback ;
   use_functor( callback );
}

Однако на данный момент я понятия не имею, как предоставить необходимые элементы данных.Поскольку структура является анонимной, у нее нет конструктора.Я мог бы легко установить элемент, потому что он общедоступный, но опять-таки это добавило бы строку, которая мне не нравится.

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

Как бы вы поступили с этим?

Ответы [ 3 ]

1 голос
/ 03 ноября 2011

Что касается инициализации переменных-членов анонимного struct без конструктора, вы можете сделать:

void function() {
   type the_thing;
   struct {
      void operator()( ... ) {...}
      type & m_member;
   } callback = {the_thing};
   use_functor( callback );
}

для установки type & ссылки m_member в callback.

0 голосов
/ 03 ноября 2011

Вы можете попробовать увеличить лямбда-библиотеку или boost :: phoenix . Они оба предназначены для выполнения лямбда-операций без реальной поддержки лямбды. Поскольку они основаны на шаблонах, ошибки могут быть сложными для отладки, когда что-то работает не так, как ожидалось.

0 голосов
/ 03 ноября 2011

Расширение ответа от awoodland:

#define MY_LAMBDA(name, memberType, memberValue, body) \
    struct {                                     \
        void operator()( ... ) body              \
        memberType & memberValue;                   \
    } name = {memberValue}

void function() {
    type thing_to_capture;

    MY_LAMBDA(callback, type, thing_to_capture
    {
        std::cout << thing_to_capture << std::endl;
    });

    use_functor( callback );
}

Вы можете использовать MY_LAMBDA везде, где можете определить структуру. К сожалению, без вариационных макросов вы должны обернуть все захваченные объекты в один объект, а также указать тип этого объекта в «объявлении лямбды»

Также обратите внимание, что эквивалент с использованием лямбды будет:

void function() {
    type thing_to_capture;

    auto callback = [&thing_to_capture]()
    {
        std::cout << thing_to_capture << std::endl;
    };

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