Ответ 1
Вам нужно объявить ваш лямбда как безгосударственный (то есть с пустой спецификацией захвата [](int x)-> bool {...}
), чтобы он мог быть преобразован в указатель функции.
Я искал везде для этого, и я, похоже, не могу найти прямой ответ. Некоторые источники говорят, что это невозможно, но это только вызывает больше вопросов для меня, о чем я расскажу ниже.
Итак, вот ситуация. Предположим, у меня есть собственный класс контейнера с функцией выбора, как показано ниже (это только пример):
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
работает с лямбда-функциями.
Я хотел бы отметить, что этот код не компилируется/протестирован как есть. Он предназначен только для демонстрации. Я попытался реализовать те же принципы в фактическом проекте, и он не работает.
Вам нужно объявить ваш лямбда как безгосударственный (то есть с пустой спецификацией захвата [](int x)-> bool {...}
), чтобы он мог быть преобразован в указатель функции.
Нет необходимости добавлять колено-рывок [&]
-capture. Ваша лямбда ему не нужна:
[] (int x) -> bool { return (x == 0); }
Captureless lambdas конвертируются в соответствующий указатель функции, поэтому это должно работать из коробки.
Тем не менее, вы должны, вероятно, объявить, что функция select принимает std::function
, к которой все лямбды конвертируются, захватываются или нет:
Container<T> select(std::function<bool(const T&)> predicate) const;