首页 > 解决方案 > 尽管明确说明了返回类型,但对 lambda 的调用是模棱两可的

问题描述

考虑到 lambda 的类型是可确定的(可转换为 an 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;
      }
   );
}

标签: c++c++11lambdaimplicit-conversionstd-function

解决方案


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

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

template< class F >
function( F f );

此构造函数不参与重载决议,除非 f 对于参数类型 Args... 和返回类型 R 是Callable。(C++14 起)

作为Callable的定义,

以下表达式必须有效:

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

其中INVOKE(f, t1, t2, ..., tN)被定义为 static_cast<void>(INVOKE(f, t1, t2, ..., tN))好像 R 可能是 cv-qualified void,否则INVOKE(f, t1, t2, ..., tN),隐式转换为 R

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


推荐阅读