Call to lambda is ambiguous despite explicitly stating the return type

Because the 2nd lambda expression returning bool could convert to both std::function<void(int)> and std::function<bool(int)> implicitly.

std::function has a converting constructor:

template< class F >
function( F f );

This constructor does not participate in overload resolution unless f is Callable for argument types Args... and return type R. (since C++14)

As the definition of Callable,

The following expressions must be valid:

INVOKE<R>(f, std::declval<ArgTypes>()...)

where INVOKE(f, t1, t2, ..., tN) is defined as static_cast<void>(INVOKE(f, t1, t2, ..., tN)) if R is possibly cv-qualified void, otherwise INVOKE(f, t1, t2, ..., tN), implicitly converted to R

Note that the 2nd lambda returning bool, for the std::function<void(int)>, as shown above, static_cast<void>(INVOKE(f, t1, t2, ..., tN)) is a valid expression (the returned bool is just converted to void). Then it could also convert to std::function<void(int)> implicitly and causes the ambiguity issue.


You can explicitly static_cast the lambda to the proper type

using FunBoolRet = std::function<bool(int)>;

do_some(static_cast<FunBoolRet >([&](int in) 
   {
      local_to_be_modified += in;
      std::cout << "This is bool-" << std::endl;
      return true;
   }));

Or store the lambda to the proper std::function<bool(int)> type and pass to the function(if do_some(lmda) should be called many times)

FunBoolRet lmda = [&](int in)
{
    local_to_be_modified += in;
    std::cout << "This is bool-" << std::endl;
    return true;
};    
do_some(lmda); // pass the lambda

Or as @MaxLanghof suggested simply construct std::function<bool(int)> from lambda on the go

do_some(FunBoolRet{
   [&](int in) 
   {
      local_to_be_modified += in;
      std::cout << "This is bool-" << std::endl;
      return true;
   }
});