尽管明确说明了 return 类型,但对 lambda 的调用是不明确的

Call to lambda is ambiguous despite explicitly stating the return type

鉴于 lambda 的类型是可确定的(可转换为 std::function(如果我错了请纠正我),重载函数应该包含两个仿函数。 问题是:尽管显式定义了 lambda 类型,为什么下面会出现编译错误? ( [&]() -> Type {} )

请注意,对于我当前的解决方案,我需要按引用捕获, 这就是代码包含它的逻辑的原因。

下面的例子描述了问题:

#include <iostream>
#include <string>    
#include <functional>

void do_some(std::function<void(int)> thing) 
{
   thing(5);
}

void do_some(std::function<bool(int)> thing)
{
   if (thing(10)) 
   {
      std::cout << "it's true!" << std::endl;
   }
}

int main()
{
   int local_to_be_modified = 0;
   do_some(
      [&](int in)
      {
         local_to_be_modified = in;
         std::cout << "This is void-" << std::endl;
      }
   );
   do_some(
      [&](int in) -> bool
      { 
         // error: call to 'do_some' is ambiguous
         local_to_be_modified += in;
         std::cout << "This is bool-" << std::endl;
         return true;
      }
   );
}

您可以显式static_cast 将 lambda 转换为正确的类型

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;
   }));

或者将 lambda 存储到正确的 std::function<bool(int)> 类型并传递给函数(如果 do_some(lmda) 应该被多次调用)

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

或如@MaxLanghof所建议 只需随时随地从 lambda 构造 std::function<bool(int)>

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

因为返回 bool 的第二个 lambda 表达式可以隐式转换为 std::function<void(int)>std::function<bool(int)>

std::function 有一个转换构造函数:

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)

作为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

注意第2个lambda返回bool,对于std::function<void(int)>,如上所示,static_cast<void>(INVOKE(f, t1, t2, ..., tN))是一个有效的表达式(返回的bool只是转换为void)。然后它也可以隐式转换为 std::function<void(int)> 并导致歧义问题。