#include <algorithm> #include <iostream> #include <functional> #include <string> void func(std::function<void(void)> param) { param(); } void func(std::function<void(int)> param) { param(5); } int main(int argc,char* argv[]) { func([] () { std::cout << "void(void)" << std::endl; }); func([] (int i) { std::cout << "void(int): " << i << std::endl; }); std::string line; std::getline(std::cin,line); return 0; }
VS2010的编译错误: –
CppTest.cpp(18): error C2668: 'func' : ambiguous call to overloaded function 1> CppTest.cpp(11): could be 'void func(std::tr1::function<_Fty>)' 1> with 1> [ 1> _Fty=void (int) 1> ] 1> CppTest.cpp(6): or 'void func(std::tr1::function<_Fty>)' 1> with 1> [ 1> _Fty=void (void) 1> ] 1> while trying to match the argument list '(`anonymous-namespace'::<lambda0>)' 1>CppTest.cpp(19): error C2668: 'func' : ambiguous call to overloaded function 1> CppTest.cpp(11): could be 'void func(std::tr1::function<_Fty>)' 1> with 1> [ 1> _Fty=void (int) 1> ] 1> CppTest.cpp(6): or 'void func(std::tr1::function<_Fty>)' 1> with 1> [ 1> _Fty=void (void) 1> ] 1> while trying to match the argument list '(`anonymous-namespace'::<lambda1>)'
编译错误从g -4.5
program2.cpp: In function ‘int main(int,char**)’: program2.cpp:18:68: error: call of overloaded ‘func(main(int,char**)::<lambda()>)’ is ambiguous program2.cpp:6:10: note: candidates are: void func(std::function<void()>) program2.cpp:11:10: note: void func(std::function<void(int)>) program2.cpp:19:79: error: call of overloaded ‘func(main(int,char**)::<lambda(int)>)’ is ambiguous program2.cpp:6:10: note: candidates are: void func(std::function<void()>) program2.cpp:11:10: note: void func(std::function<void(int)>)
所以似乎编译器无法弄清楚一个lambda []() – > void只能分配给std :: function< void(void)>和lambda [](int) – > void只能分配给std :: function< void(int)> ;.这是应该发生还是仅仅是编译器的缺陷?
解决方法
Is this supposed to happen or just a deficiency in the compilers?
这应该会发生. std :: function具有可以接受任何类型参数的构造函数模板.编译器直到选择构造函数模板并实例化才能运行到错误之后才能知道,并且必须能够在执行此操作之前选择一个重载函数.
最简单的修复是使用转换或显式构造正确类型的std :: function对象:
func(std::function<void()>([](){})); func(std::function<void(int)>([](int){}));
如果你有一个编译器支持captureless-lambda-to-function-pointer转换,而lambda没有捕获任何东西,你可以使用raw函数指针:
void func(void (*param)()) { } void func(void (*param)(int)) { }
(看起来您正在使用Visual C 2010,它不支持此转换.直到Visual Studio 2010发布之前,转换没有添加到规范中,太晚才能添加.)
为了更详细地解释这个问题,请考虑以下几点:
template <typename T> struct function { template <typename U> function(U f) { } };
这基本上是什么样的std :: function构造函数看起来像:你可以使用任何参数调用它,即使参数没有意义,并会导致其他地方的错误.例如,函数< int()> F(42);将使用U = int调用此构造函数模板.
在您的具体示例中,编译器在重载解析期间找到两个候选函数:
void func(std::function<void(void)>) void func(std::function<void(int)>)
参数类型,我们将引用为F的一些不可比拟的lambda类型名称与这些不完全匹配,因此编译器开始查看可以对F进行什么转换,以使其匹配这些候选函数之一.寻找转换时,会找到上述的构造函数模板.
>它可以将F转换为std :: function< void(void)>使用其转换构造函数U = F和
>它可以将F转换为std :: function< void(int)>使用U = F的转换构造函数
在你的例子中,显而易见的是,只有其中的一个将成功,而没有错误,但在一般情况下,这是不正确的.编译器无法做任何进一步的操作.它必须报告模糊和失败.它不能选择一个,因为两个转换都是同样好的,没有超负荷比另一个更好.