C ++ 2 слоя возвратов в лямбда-функциях - PullRequest
1 голос
/ 30 апреля 2020

У меня есть код, который возвращает название города и население, только если население превышает 5 миллионов.

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;

template <typename C>
static auto opt_print(const C& container) {
    return [end_it (end(container))] (const auto& item) {
        if (item != end_it) {
            cout << *item << endl;
        }
        else {
            cout << "<end>" << endl;
        }
    };
}

struct city {
    string name;
    unsigned population;
};

bool operator==(const city& a, const city& b) {
    return (a.name == b.name && a.population == b.population);
}

ostream& operator<<(ostream& os, const city& c) {
    return os << "{" << c.name << ", " << c.population << "}";
}

int main() {
    const vector<city> c {
        {"NYC", 8398748},
        {"LA", 3990456},
        {"Chicago", 2705994},
        {"Houston", 2325502}
    };

    auto print_city (
        opt_print(c)
    );

    auto population_more_than (
        [] (unsigned i) {
            return [=] (const city& item) {
                return (item.population > i);
            };
        }
    );
    auto found_large(
        find_if(
            begin(c),
            end(c),
            population_more_than(5000000)
        )
    );
    print_city(found_large);

    return 0;
}

У меня есть следующие вопросы:

  1. Чего я не понимаю, так это лямбда-функции population_more_than: зачем мне два слоя лямбда-функций? Есть ли способ упростить код?

  2. Что здесь делает [=]? По определению лямбда-функции [=] означает принятие всех внешних переменных по значению, что принимает [=]? Отнимает ли он только часть unsigned i от внешнего слоя?

  3. Если я хочу изменить лямбда-функцию population_more_than на следующую: auto population_more_than ( [&each_city] (unsigned i) { return (each_city.population > i); } ); Как мне изменить auto found_large Лямбда-функция часть соответственно? Он уже основан на итераторе, но я не могу запустить код ...

Ответы [ 3 ]

3 голосов
/ 30 апреля 2020

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

auto found_large {
    std::find_if(
        std::begin(c),
        std::end(c),
        [] (city const& item) -> bool {
            return item.population > 5'000'000;
        }
    )
};

Способность улучшить express намерение с чем-то вроде population_more_than(5'000'000) обычно является лучшим выбором дизайна, хотя в долгосрочной перспективе.

1 голос
/ 30 апреля 2020

Что я не понимаю, так это лямбда-функция population_more_than: зачем мне два слоя лямбда-функций? Есть ли способ упрощения кода?

Он отделяет прохождение int от прохождения city. Обратите внимание, что несколько городов сравниваются с тем же int позже. std::find_if нужен вызываемый как bool(city), а не bool(city, int)

Что здесь делает [=]? По определению лямбда-функции [=] означает принятие всех внешних переменных по значению, что принимает это [=]? Это берет только часть без знака из внешнего слоя?

Да.

Если я хочу изменить лямбда-функцию pop_more_than ниже: auto population_more_than ( [&each_city] (unsigned i) { return (each_city.population > i); } ); Как мне соответственно изменить часть лямбда-функции auto found_large?

found_large is не лямбда. Это std::vector<city>::const_iterator. Чтобы использовать population_more_than, вам понадобится несколько int s, чтобы вызвать его, и city each_city;, определенное до population_more_than

1 голос
/ 30 апреля 2020
  1. population_more_than - это лямбда, которая return sa лямбда, в данном случае, так что вторая лямбда может поддерживать разные популяции. Вам не нужны два уровня функций, но это приводит к чистому дизайну, поскольку вы можете вызвать population_more_than(15) и получить другую функцию предиката.
  2. [=] действительно собирает локальные данные по значению. В этом случае единственная переменная, которую он собирается скопировать, это i, поскольку это единственная переменная, которую вы используете.
  3. Что такое each_city? Что вы ожидаете i? Текущая версия занимает city, а ваша новая версия - unsigned, поэтому вы не согласны с тем, как, по вашему мнению, это работает.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...