I'm trying to initialise a lambda function and then passing as a predicate to std::find_if but receiving the following compiler error. "expression cannot be used as a function".
So how do you first initialise a lambda as a type auto variable and pass it in as a predicate function to an algorithm like std::find_if?
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<std::string> vec ={"this", "is", "a", "test", "to",
"see","if", "this", "works", "to", "this", "if"};
auto elimDups_lambda
{
[&vec]()
{
std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
return vec;
}
};
for(auto& iter_vec:elimDups_lambda())
std::cout<<iter_vec<<std::endl;
auto lambda_size
{
[&vec](size_t x)
{
for(auto& iter_vec:vec)
{
if(iter_vec.size()==x)
return true;
else if(iter_vec >*vec.end())
return false;
}
}
};
size_t string_size =0;
std::cin>>string_size;
std::vector<std::string>::iterator find_word =
std::find_if(vec.begin(), vec.end(), lambda_size(string_size));
std::cout<<*find_word<<std::endl;
return 0;
}
Thank you.
CodePudding user response:
In order to define a variable holding a lambda, you can use syntax similar to this:
auto lambda_var =
[&vec]()
{
std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
return vec;
};
To use it when calling std::find_if
, pass lambda_var
(or the name of the variable holding the lambda that you need), as a 3rd parameter to std::find_if
in your code elimDups_lambda
and lambda_size
are not properly defined to be variables holding lambdas (if this is indeed what you wanted to achieve).
CodePudding user response:
With the expression
lambda_size(string_size)
you call the lambda function, and then the returned bool
result will be used as the predicate for std::find_if
.
This will of course not work very well.
You can solve this in two ways:
Capture
string_size
in the lambda; OrMake the lambda return another lambda for the size check:
auto lambda_size = [&vec](size_t size) { return [size](std::string const& word) { return word.length() == size; } }
Also note how I have changed the logic in the lambda for the comparisons. Your comparison could mean that you dereference the end()
iterator for the vector, which isn't allowed. And also that there's a path where the lambda doesn't actually return anything.
Both those problems inside the lambda would lead to undefined behavior.