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.
5 Answers 5
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.
Comments
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->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
Get V as parameter to the lambda.
std::find_if(V.begin(), V.end(), [&Name](type& V) {return Name == V->info.name;)
Comments
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
returnif nothing found?