Передача лямбда-функций C ++ - PullRequest
30 голосов
/ 27 сентября 2011

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

Итак, вот ситуация.Предположим, у меня есть собственный контейнерный класс с функцией выбора, как показано ниже (это только пример):

template <typename T>
class Container {
public:
    // ...

    Container<T> select(bool (*condition)(const T&)) const;

    // ...
};

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

bool zero_selector(const int& element) {
    return (element == 0); // Selects all elements that are zero
}

Теперь, если у меня есть контейнер, заполненный, скажем, s = { 1, 1, 0, 0, 1, 0, 1, 0 }, я мог бы выбрать подмножество из них, которое будет содержать только нули, используя:

t = s.select(&zero_selector); // t = { 0, 0, 0, 0 }

Как видите, это немного неуклюже.Лямбда-функции сделали бы это намного более элегантным, так что тогда я мог бы использовать (я не уверен, что это правильный синтаксис для него), например:

t = s.select([&] (int x) -> bool { return (x == 0); });

Мой вопрос, возможно ли это?Если да, то каким должен быть мой прототип функции, чтобы Container::select() мог принимать лямбду в качестве одного из своих параметров?

Если это невозможно, то как реализовать что-то вроде std::for_each, которое может использовать лямбду?Выражение как один из его аргументов?Любые ресурсы, которые бы четко объяснили это, будут высоко оценены.Все, что я нашел, просто приводит примеры лямбда-функций и использования std::function<> для передачи их в качестве параметров, но ничего не объясняет, как std::for_each работает с лямбда-функциями.

Я хотел бы отметить, что этот код нене скомпилировано / протестировано как есть.Это только для демонстрационных целей.Я пытался реализовать те же принципы в реальном проекте, и он не работает.

Ответы [ 2 ]

40 голосов
/ 27 сентября 2011

Нет необходимости добавлять коленный рывок [&] -захват.Ваша лямбда не нуждается в этом:

[] (int x) -> bool { return (x == 0); }

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

Тем не менее, вы, вероятно, должны объявитьвыберите функцию для принятия std::function, к которой все лямбды могут быть конвертируемыми, с захватом или без:

Container<T> select(std::function<bool(const T&)> predicate) const;
17 голосов
/ 27 сентября 2011

Вам нужно объявить вашу лямбду как не имеющую состояния (то есть с пустой спецификацией захвата [](int x)-> bool {...}), чтобы она могла быть преобразована в указатель на функцию.

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