10

I have a function that searches a vector of iterators and returns the iterator if its names matches a string passed as an argument.

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];
    }
}

My question is how can I implement this as a lambda, to use it in connection with std::find_if?

I'm trying this:

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

But it says that V

an enclosing-function local variable cannot be referenced in a lambda body unless it is in the capture list.

1
  • 1
    No return if nothing found? Commented Mar 19, 2019 at 21:26

5 Answers 5

22

find_if is going to pass the elements of the vector into your lambda. That means you need

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

so that the V in the lambda body is the element of the vector, not the vector itself.


Ideally you'd give it a different name than V so you keep the vector and local variables separate like

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

So now it is clear you are working on a element of the vector, instead of the vector itself.

Sign up to request clarification or add additional context in comments.

Comments

8

First, V->info.name is ill formed, inside or outside of the lambda.

The function object sent to the algoritm std::find_if must be a unary function. It must take the current element to check as a parameter.

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

The type of found is an iterator to the element that has been found. If none is found, then it returns V.end()

If you use C++14 or better, you can even use generic lambdas:

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

4 Comments

V->info.name is valid syntax. It just won't typecheck since vectors don't overload ->.
It just won't typecheck since vectors don't overload -> so... it won't compile? It's an invalid syntax to use -> on object of types that don't overload operator->
Not all compile errors are syntax errors. See syntax vs. semantics.
@SilvioMayolo The answer you linked me says that semantics is the meaning of the program, usually in it's runtime behaviour. The code I quoted is simply ill formed, there is no semantic yet. Or maybe I don't understand the concept correctly
4

std::find_if's predicate will receive a reference to each element of the range in turn. You need:

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

Comments

2

Get V as parameter to the lambda.

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

Comments

1

Use const auto & to access the individual elements from your vector in the lambda expression. Since the vector is an lvalue, auto will be deduced to const vector<PVertex> &. Then, you can use std::distance to find the element location of the object in the vector.

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;
}

Result is:

found at: V[2]

Example: https://rextester.com/IYNA58046

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.