如果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;
}
);
}
bool
的第二个lambda表达式可以隐式转换为std::function<void(int)>
和std::function<bool(int)>
。
std::function
有一个转换构造函数:
template< class F > function( F f );
此构造函数不参与重载解析,除非f对于参数类型Args是可调用的。。。和返回类型R(由于C++14(
作为可调用、的定义
以下表达式必须有效:
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
刚刚转换为void
(。然后它也可以隐式地转换为std::function<void(int)>
,从而引起歧义问题。
您可以显式地将lambdastatic_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;
}
});