我有一个函数可以遍历容器并将每个元素传递给谓词进行过滤。此函数的重载还将每个元素的索引传递到谓词中。
template<typename TContainer>
void DoSomethingIf(TContainer &c, std::function<bool (const typename TContainer::const_reference)> predicate);
template<typename TContainer>
void DoSomethingIf(TContainer &c, std::function<bool (const typename TContainer::const_reference, int)> predicate);
我发现尝试使用裸 lambda 调用这些函数中的一个会导致 VC11 中的编译器错误,而使用 std::function 对象会成功:
void foo()
{
std::vector<int> v;
// fails
DoSomethingIf(v, [](const int &x) { return x == 0; });
// also fails
auto lambda = [](const int &x) { return x == 0; };
DoSomethingIf(v, lambda);
// success!
std::function<bool (const int &)> fn = [](const int &x) { return x == 0; };
DoSomethingIf(v, fn);
}
1>c:\users\moswald\test.cpp(15): error C2668: 'DoSomethingIf' : ambiguous call to overloaded function
1> c:\users\moswald\test.cpp(8): could be 'void DoSomethingIf<std::vector<_Ty>>(TContainer &,std::function<_Fty>)'
1> with
1> [
1> _Ty=int,
1> TContainer=std::vector<int>,
1> _Fty=bool (const int &,int)
1> ]
1> c:\users\moswald\test.cpp(5): or 'void DoSomethingIf<std::vector<_Ty>>(TContainer &,std::function<_Fty>)'
1> with
1> [
1> _Ty=int,
1> TContainer=std::vector<int>,
1> _Fty=bool (const int &)
1> ]
1> while trying to match the argument list '(std::vector<_Ty>, foo::<lambda_8EADDE04A8D35A3C>)'
1> with
1> [
1> _Ty=int
1> ]
1>c:\users\moswald\test.cpp(19): error C2668: 'DoSomethingIf' : ambiguous call to overloaded function
1> c:\users\moswald\test.cpp(8): could be 'void DoSomethingIf<std::vector<_Ty>>(TContainer &,std::function<_Fty>)'
1> with
1> [
1> _Ty=int,
1> TContainer=std::vector<int>,
1> _Fty=bool (const int &,int)
1> ]
1> c:\users\moswald\test.cpp(5): or 'void DoSomethingIf<std::vector<_Ty>>(TContainer &,std::function<_Fty>)'
1> with
1> [
1> _Ty=int,
1> TContainer=std::vector<int>,
1> _Fty=bool (const int &)
1> ]
1> while trying to match the argument list '(std::vector<_Ty>, foo::<lambda_8EADDE04A8D35A3D>)'
1> with
1> [
1> _Ty=int
1> ]
这是意料之中的吗?是否有不同的方法来重载这些函数(没有将一个重命名为“DoSomethingIfWithIndex
”?
最佳答案
预计会出现过载歧义。
std::function
有一个可以接受任何参数的转换构造函数模板。只有在构造函数模板被实例化后,编译器才能确定它会拒绝该参数。
在您的第一个和第二个示例中,都需要用户定义的转换来将未指定的 lambda 类型转换为每个 std::function
类型。两种转换都不是更好(它们都是用户定义的转换),因此编译器会报告重载歧义。
在您的第三个示例(有效的示例)中,没有歧义,因为未使用 std::function
构造函数模板。相反,它使用了它的复制构造函数(并且,在所有其他条件相同的情况下,非模板优先于模板)。
关于c++ - C++ lambda 不能正确选择重载函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9339717/