下面的代码不能在gcc 4.5上编译,因为对foo的调用是不明确的。消除歧义的正确方法是什么?
#include <iostream>
#include <functional>
using namespace std;
void foo(std::function<void(int, int)> t)
{
t(1, 2);
}
void foo(std::function<void(int)> t)
{
t(2);
}
int main()
{
foo([](int a, int b){ cout << "a: " << a << " b: " << b << endl;});
}
答案 0 :(得分:6)
最好的方法是显式创建一个正确类型的std::function
对象,然后将该对象传递给函数:
std::function<void(int, int)> func =
[](int a, int b) { cout << "a: " << a << " b: " << b << endl; }
foo(func);
或内联:
foo(
std::function<void(int, int)>(
[](int a, int b) { cout << "a: " << a << "b: " << b << endl; }
));
std::function
有一个构造函数模板,可以接受任何内容:
template<class F> function(F);
因此,编译器无法在重载决策期间知道要选择foo
:std::function<void(int)>
和std::function<void(int, int)>
都有一个构造函数可以将lambda表达式作为参数。
直接传递std::function
对象时,std::function
复制构造函数在重载解析期间是首选,因此选择它而不是构造函数模板。
回答未来:如果保证捕获列表为空,您还可以使用普通函数指针。在C ++ 0x中,无捕获的lambda可以隐式转换为函数指针。所以,你可以使用像
这样的东西void foo(void (*t)(int, int)) { t(1, 2); }
void foo(void (*t)(int)) { t(1); }
并使用无捕获的lambda(或具有匹配类型的函数指针)直接调用foo
。
请注意,此转换是草案语言标准的最新补充(它已于今年2月添加),因此它不太可能得到广泛支持。 Visual C ++ 2010还不支持它;我不知道最新的g ++。
答案 1 :(得分:3)
我最近一直在考虑类似的问题,在寻找任何已知的解决方案时,我遇到了这篇文章,并且缺乏解决方案
另一种解决方案是将仿函数抽象为模板参数,并使用decltype来解析其类型。所以,上面的例子将成为:
#include <iostream>
#include <functional>
using namespace std;
template<class F>
auto foo(F t) -> decltype(t(1,2))
{
t(1, 2);
}
template<class F>
auto foo(F t) -> decltype(t(2))
{
t(2);
}
int main()
{
foo([](int a, int b){ cout << "a: " << a << " b: " << b << endl;});
}
这与gcc 4.5一样正常。