Подтвердить что ты не робот

Передача лямбда-функций С++

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

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

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 работает с лямбда-функциями.

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

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

Container<T> select(std::function<bool(const T&)> predicate) const;