鉴于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;
}
);
}
答案 0 :(得分:8)
因为第二个lambda表达式返回bool
可以隐式转换为std::function<void(int)>
和std::function<bool(int)>
。
std::function
具有转换构造函数:
template< class F > function( F f );
除非参数类型为Args的f为 Callable ,并且返回类型R,此构造函数不参与重载解析(自C ++ 14起)
作为Callable的定义,
以下表达式必须有效:
INVOKE<R>(f, std::declval<ArgTypes>()...)
其中 INVOKE(f,t1,t2,...,tN)定义为
static_cast<void>(INVOKE(f, t1, t2, ..., tN))
,如果R可能是 cv合格的void
,否则为 INVOKE(f,t1,t2,...,tN)隐式 转换为R
请注意,对于bool
,第二个lambda返回std::function<void(int)>
,如上所示,static_cast<void>(INVOKE(f, t1, t2, ..., tN))
是有效的表达式(返回的bool
只是转换为{{ 1}})。然后它也可能隐式转换为void
并引起歧义问题。
答案 1 :(得分:6)
您可以将lambda明确static_cast
设置为正确的类型
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;
}
});