尽管明确说明了 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)>
并导致歧义问题。
鉴于 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-qualifiedvoid
, 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)>
并导致歧义问题。