重载std :: function参数以匹配lambda

Chr*_*odd 11 c++ lambda g++ c++11

可能重复:
消除对带有std :: functions的函数的调用
不是它的类型的std :: function部分的模板参数(签名)?

我想重载一个函数,以便可以使用各种不同的lambda(通常带有更多或更少的参数)来调用它.我试过的显而易见的事情是:

#include <functional>
#include <iostream>

extern void fn(std::function<void(int)>);
extern void fn(std::function<void(int, int)>);

void test()
{
    fn([](int a) { std::cout << "lambda with 1 arg " << a << std::endl; });
}
Run Code Online (Sandbox Code Playgroud)

但是,这与g ++(试过v4.6.2和v4.7.1)失败并出现错误:

test.cc: In function ‘void test()’:
test.cc:9:74: error: call of overloaded ‘fn(test()::<lambda(int)>)’ is ambiguous
test.cc:9:74: note: candidates are:
test.cc:4:13: note: void fn(std::function<void(int)>)
test.cc:5:13: note: void fn(std::function<void(int, int)>)
Run Code Online (Sandbox Code Playgroud)

现在我在这里这里找到了另一种(也就是更复杂的)方法,但我的问题是,为什么上面的代码失败了?标准中是否有某些内容表明它无法正常工作,或者这仅仅是g ++的错误/限制?

Mr.*_*bis 5

每个Lambda [](int a) { std::cout << "lambda with 1 arg " << a << std::endl; } 都有唯一的类型,即使是与上面相同的另一个lambda,也会产生与成员不同的lambda类型operator()(int a)

你的实现std::function具有可通过两种使用的模板转换 std::function<void(int)>std::function<void(int, int)>.虽然实例化时只有其中一个编译,但它们都被认为是重载解析,这就是产生歧义的原因.为了获得所需的结果,库需要使用SFINAE从过载候选集中排除错误的一个(libc ++的最新版本就是这样).