C ++ лямбда-синтаксис - PullRequest
9 голосов
/ 19 марта 2019

У меня есть функция, которая ищет вектор итераторов и возвращает итератор, если его имена совпадают со строкой, переданной в качестве аргумента.

koalaGraph::PVertex lookUpByName(std::string Name, std::vector<koalaGraph::PVertex>& Vertices) {

    for (size_t i = 0; i < Vertices.size(); i++) {

        if(Vertices[i]->info.name == Name) 
            return Vertices[i];
    }
}

У меня вопрос, как я могу реализовать это как лямбда, чтобыиспользовать это в связи с std::find_if?

Я пытаюсь это сделать:

std::vector<koalaGraph::PVertex> V;
std::string Name;
std::find_if(V.begin(), V.end(), [&Name]() {return Name == V->info.name;})

Но он говорит, что V

На локальную переменную функции включения нельзя ссылаться в лямбда-телеесли только он не находится в списке захвата.

Ответы [ 5 ]

20 голосов
/ 19 марта 2019

find_if собирается передать элементы вектора в вашу лямбду. Это означает, что вам нужно

std::find_if(V.begin(), V.end(), [&Name](auto const& V) {return Name == V->info.name;})

так, что V в теле лямбды является элементом вектора, а не самого вектора.


В идеале вы бы дали ему имя, отличное от V, поэтому вы держите вектор и локальные переменные отдельно, как

std::find_if(V.begin(), V.end(), [&Name](auto const& element) {return Name == elememt->info.name;})

Итак, теперь ясно, что вы работаете с элементом вектора вместо самого вектора.

8 голосов
/ 19 марта 2019

Во-первых, V->info.name плохо сформирован, внутри или снаружи лямбды.

Объект функции, отправляемый алгоритму std::find_if, должен быть унарной функцией. Он должен взять текущий элемент для проверки в качестве параметра.

auto found = std::find_if(
    V.begin(), V.end(), 
    [&Name](koalaGraph::PVertex const& item_to_check) {
        return Name == item_to_check->info.name;
    }
);

Тип found является итератором для найденного элемента. Если ничего не найдено, возвращается V.end()

Если вы используете C ++ 14 или выше, вы можете даже использовать общие лямбды:

auto found = std::find_if(
    V.begin(), V.end(), 
    [&Name](auto const& item_to_check) {
        return Name == item_to_check->info.name;
    }
);
4 голосов
/ 19 марта 2019
Предикат

std::find_if будет получать ссылку на каждый элемент диапазона по очереди. Вам нужно:

std::find_if(
    V.begin(), V.end(),
    [&Name](koalaGraph::PVertex const &v) { return Name == v->info.name; }
);
2 голосов
/ 19 марта 2019

Получить V в качестве параметра для лямбды.

std::find_if(V.begin(), V.end(), [&Name](type& V) {return Name == V->info.name;)

1 голос
/ 19 марта 2019

Используйте const auto & для доступа к отдельным элементам вашего вектора в лямбда-выражении. Поскольку вектор является lvalue, значение auto будет выведено на const vector<PVertex> &. Затем вы можете использовать std::distance, чтобы найти расположение элемента объекта в векторе.

struct PVertex
{
    std::string name;
};

int main()
{
    std::vector<PVertex> V = {{"foo"},{"bar"},{"cat"},{"dog"}};

    std::string Name = "cat";

    auto found = std::find_if(std::begin(V), std::end(V), [&Name](const auto &v){return (Name == v.name);});

    std::cout<< "found at: V["<<std::distance(std::begin(V),found)<<"]" <<std::endl;
}

Результат:

found at: V[2]

Пример: https://rextester.com/IYNA58046

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