所以,我有一个方法及其对类的重载,如下所示:
bool my_for_each(someIterator begin, someIterator end, bool (*_lambda)(someIterator));
void my_for_each(someIterator begin, someIterator end, void (*_lambda)(someIterator));
正如您所看到的,唯一的区别是传递函数的签名,即其返回类型。 虽然我称之为上面的代码完全正常:
my_for_each(iteratorBegin, iteratorEnd, [](someIterator) {; }); // calls void version
my_for_each(iteratorBegin, iteratorEnd, [](someIterator)->bool {return false; }); // calls bool version
...,如果我按如下方式编写my_for_each函数:
bool my_for_each(someIterator begin, someIterator end, std::function<bool(someIterator)> _lambda);
void my_for_each(someIterator begin, someIterator end, std::function<void(someIterator)> _lambda);
如果我以相同的方式调用函数(C2668模糊调用重载函数),则代码无法编译。虽然,如果我手动转换函数:
my_for_each(iteratorBegin, iteratorEnd, static_cast<std::function<void(someIterator)>>([](someIterator) {; })); //calls void version
my_for_each(iteratorBegin, iteratorEnd, static_cast<std::function<bool(someIterator)>>([](someIterator) -> bool { return false; })); //calls bool version
代码完美无缺。所以我只是想知道:
编译器是VS2015。
谢谢,祝你有愉快的一天!
答案 0 :(得分:3)
std::function
和lambdas具有不同的类型,这意味着第二个示例需要从lambda的类型到std::function
的隐式转换。
问题是返回bool
的lambda可以隐式转换为std::function<bool(T)>
和std::function<void(T)>
,因此两次重载都是调用同样有效的选择,导致歧义错误。当您手动将它们转换为正确的std::function
时,明确解决了歧义。
修改:解决方法
您可以通过提供接受任何类型的可调用类型的附加模板化重载来解决此问题,推导出该可调用类型的返回类型并自动执行强制转换。我已将someIterator
更改为模板参数以获得通用性。由于您尚未提供my_for_each
函数的实现详细信息,因此我省略了这些实现。由于您似乎只想支持void
和bool
返回类型,因此我提供了static_assert
来生成明确的编译器错误,以防提供不支持的返回类型。< / p>
#include <functional>
#include <type_traits>
// Implement for std::function<bool(iter)>
template<class I>
bool my_for_each(I begin, I end, std::function<bool(I)> lambda);
// Implement for std::function<void(iter)>
template<class I>
void my_for_each(I begin, I end, std::function<void(I)> lambda);
// Dispatch to the right overload
template<class T, class I>
auto my_for_each(I begin, I end, T&& lambda)
{
using return_type = decltype(lambda(begin)); // Obtain the return type of lambda
static_assert(std::is_same<return_type, bool>::value || std::is_same<return_type, void>::value,
"my_for_each only accepts function objects that return void or bool");
using function_type = std::function<return_type(I)>; // The type to cast lambda to
return my_for_each(begin, end, function_type(std::forward<T>(lambda))); // Preform the cast
}
答案 1 :(得分:2)
原因是非捕获lambda只能转换为函数指针,它接受使用类型的参数。
另一方面,std::function
有一个模板化的构造函数,它接受所有东西。因此,std::function<bool...>
和std::function<void ...>
都可以从lambda中创建,以便重载my_for_each
。 (注意,虽然不可能创建这些对象。)