I wonder why std::function<...(...)> &
needs to be specified as const
when passed as an input parameter to a function. AFAIK there is no way to change it, right? Here is an example that compiles and runs fine. If I remove the const
qualifier I get an error:
#include <iostream>
#include <functional>
//int foo(std::function<int(int)> &f)
int foo(const std::function<int(int)> &f)
{
return f(6);
}
int main(int argc, char **argv)
{
auto f1 = [=](int i){ if (i<5) {return 8*2;} else {return 2;} };
auto f2 = [=](int i){ if (i>3) {return i*i;} else {return 2;} };
std::cout << foo(f1) << "\n";
}
When I use the declaration without the const
I get the following error:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:13:21: error: cannot bind non-const lvalue reference of type ‘std::function<int(int)>&’ to an rvalue of type ‘std::function<int(int)>’
std::cout << foo(f1) << "\n";
^
In file included from /usr/include/c++/7/functional:58:0,
from main.cpp:2:
/usr/include/c++/7/bits/std_function.h:685:7: note: after user-defined conversion: std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = main(int, char**)::<lambda(int)>; <template-parameter-2-2> = void; <template-parameter-2-3> = void; _Res = int; _ArgTypes = {int}]
function<_Res(_ArgTypes...)>::
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:4:5: note: initializing argument 1 of ‘int foo(std::function<int(int)>&)’
int foo(std::function<int(int)> &f)
^~~
A lambda is not a std::function
, but a std::function
can be created from a lambda. When you pass either f1
or f2
to foo()
, the compiler must construct a temporary std::function
object to give to the f
parameter. However, an lvalue reference to a non-const
object cannot be bound to a temporary object, exactly as the error message says.
To allow the passing of a temporary object, the f
parameter must be changed to take the std::function
by either:
const
objectOtherwise, you have to construct the std::function
yourself in a variable, then pass that instead:
#include <iostream>
#include <functional>
//int foo(const std::function<int(int)> &f)
int foo(std::function<int(int)> &f)
{
return f(6);
}
int main(int argc, char **argv)
{
auto f1 = [=](int i){ if (i<5) {return 8*2;} else {return 2;} };
auto f2 = [=](int i){ if (i>3) {return i*i;} else {return 2;} };
std::function<int(int)> f = f1;
std::cout << foo(f) << "\n";
}