I\'m having trouble in detecting why the heck is this not compiling. I\'ve got some lambda function that returns a std::function
based on some argument.
some_fun
wants argument of type const std::function<void(int)> &
.
std::bind returns "a function object of unspecified type T" (look at provided link, section "Return value"), that you are trying to pass as some_fun argument.
It seems this causes problem, because this argument type is not expected.
Look at: http://en.cppreference.com/w/cpp/utility/functional/bind
std::bind expressions, like their boost::bind
predecessors, support a type of composition operation. Your expression for w
is roughly equivalent to
auto w=std::bind(some_fun, std::bind(&foo::bar<int>, x, std::placeholders::_1) );
Nesting binds in this manner is interpreted as
x.bar<int>(y)
where y
is the first parameter passed into the resulting functor.some_fun
.But x.bar<int>(y)
returns void, not any function type. That's why this doesn't compile.
As K-ballo points out, with boost::bind
, you can fix this problem with boost::protect
. As Kerrek SB and ildjarn point out, one way around this issue is: don't use auto
for f
. You don't want f
to have the type of a bind expression. If f
has some other type, then std::bind
won't attempt to apply the function composition rules. You might, for instance, give f
the type std::function<void(int)>
:
std::function<void(int)> f = std::bind(&foo::bar<int>, x, std::placeholders::_1);
auto w = std::bind(some_fun, f);
Since f
doesn't literally have the type of a bind expression, std::is_bind_expression<>::value
will be false on f
's type, and so the std::bind
expression in the second line will just pass the value on verbatim, rather than attempting to apply the function composition rules.