I have a list of numbers.
I am trying to filter the list and only keep the positive numbers.
I am trying to do it by passing a lambda as an argument.
I wonder why I get function mismatch error.
#include <vector>
#include <algorithm>
#include <functional>
template<typename T>
std::vector<T> keep(
const std::vector<T> &original,
std::function<bool(const T&)> useful)
{
std::vector<T> out;
for(T item:original)
{
if(useful(item))
out.push_back(item);
}
return out;
}
int main()
{
std::vector<int> a={4,6,2,-5,3,-8,13,-11,27};
a=keep(a,[](const int& x)->bool{return x>0;});
for(int y:a)
{
std::cout<<y<<std::endl;
}
return 0;
}
And this is the error message:
error: no matching function for call to ‘keep(std::vector<int>&, main()::<lambda(const int&)>)’
a=keep(a,[](const int& x)->bool{return x>0;});
^
Change the function
keep
toLive example.
This works with an argument to
useful
being any one of these:std::function
From the documentation:
This means that two lambdas with the same code, would generate two different typed objects.
However, both of these are implicitly convert-able to the corresponding
std::function
types:But then why doesn't it work in your case? This is because of template type deduction. Changing
keep
towill make your example compile without any cast at the caller site.
However, trying to match it against
std::function<T>
won't work since template type deduction doesn't consider any conversion. Template argument deduction looks for exact type matches. Implicit conversions don't matter at this stage. You've to explicitly cast it to a matchingstd::function
as Atomic_alarm comments. Like Joseph says in How to convert a lambda to an std::function using templates:While in the alternative solution what happens is something like this:
The type of
f
here is notstd::function
but some unnamed type deduced like it would for the template parameterFunc
above.If you still want to do it the
std::function
way, see this answer which does it with an additional template indirection. See this answer and this post for related details.