Вызов функции объекта в лямбде for_each?

0

Я пытаюсь справиться с лямбдами в C++.

Здесь мой код (переменные, упрощенные для понимания):

template <typename Container>
void do_function(const Container& c, const item &w){

complex<double> a(w.x1, w.y1);
complex<double> b(w.x3, w.y3);

for_each(begin(c), end(c), [] {
    p->inner_function(a, b);
});
}

Я знаю, что p ничего не значит, это просто для того, чтобы проиллюстрировать, что я хочу делать.

По сути, я хочу использовать эту функцию для любого типа контейнера (list/vector и т.д.), Который содержит экземпляры указателей абстрактного класса Animal. Все эти экземпляры имеют реализацию "inner_function (complex, complex)".

Я хочу вызвать эту функцию для каждого из них в цикле for_each, используя lambdas в C++ 11..

Однако примеры онлайн все немного запутывают.

  • 0
    Что не так с тем, что ты делаешь?
  • 0
    Ну, во-первых, «p» не было объявлено, и, очевидно, «режим захвата» не был указан, поэтому он не знает, что такое a и b.
Теги:
c++11
foreach
lambda

3 ответа

4
Лучший ответ

Кажется, вы хотите использовать

std::for_each(std::begin(c), std::end(c), [=](Animal* p) { p->inner_function(a, b); });

Ваша лямбда-функция должна будет принять один аргумент, поскольку std::for_each() ожидает функцию, которая может быть вызвана с результатом *std::begin(c). Аргументы должны быть явно объявлены. Вам также необходимо выбрать способ захвата аргументов a и b. Использование [] означает, что нет захваченного контекста, и вы не можете получить доступ к каким-либо локальным переменным вообще. Вы можете использовать

  • [=] чтобы зафиксировать все переменные в контексте по значению.
  • [&] чтобы фиксировать все переменные в контексте по ссылкам.
  • вы можете переопределить установленную по умолчанию, явно указав переменные:
    • [=,&a] будет захватывать b по значению и a в качестве ссылки.
    • [&,b] то же самое, но начиная с другого значения по умолчанию
    • [&a,b] то же, но явно перечисляет все аргументы.

Может быть проще использовать выражение std::bind(), на самом деле:

std::for_each(std::begin(c), std::end(c), std::bind(&Animal::inner_function, _1, a, b));

Так как вы не задавали вопрос, неясно, в чем вопрос.

  • 0
    Это прекрасно, и я действительно понимаю, почему сейчас. По сути, я не был уверен, что использовать, когда вы использовали (Animal * p), и я не знал о [=] и [&]. Спасибо!
2

Если Container будет vector<Animal*>, list<shared_ptr<Animal>> т.д., Тогда я думаю, что вы хотите:

for_each(begin(c), end(c), [&](typename Container::value_type p) {
    p->inner_function(a, b);
});

Чтобы также поддерживать unique_ptr, вы можете сделать его typename Container::value_type const &p.

Или используйте "диапазон для цикла":

for(auto p : c) {
    p->inner_function(a, b);
}

Точно так же, как опция auto & разрешить не скопировать p.

  • 0
    typename Container::value_type
  • 0
    @ bames53: я знаю, что должен помнить, является ли объявление параметра лямбды контекстом, который подразумевает тип, но я верю вашему слову :-)
Показать ещё 1 комментарий
1

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

std::vector<std::unique_ptr<Animal>> v;
item w;

do_function(v, w);

Алгоритм std::for_each передает каждый элемент в функтор. Он передает их таким образом, что функтор может принимать аргумент либо по значению, либо по ссылке при необходимости. unique_ptr необходимо использовать по ссылке:

for_each(begin(c), end(c), [] (std::unique_ptr<Animal> &p) {
    p->inner_function(a, b);
});

Функтору также нужен доступ к a и b. Вы можете зафиксировать их явно:

[a,b] (std::unique_ptr<Animal> &p) {

Или, как говорит Стив Джессоп, просто использовать диапазон на основе for, что гораздо проще. С unique_ptr это выглядело бы так:

for(auto &p : c) {
    p->inner_function(a, b);
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню