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; });
}

但是,这会因 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)>)

现在我在这里这里找到了另一种(更复杂的)方法,但我的问题是,为什么上面的代码会失败?标准中有什么东西说它不能工作,还是这仅仅是 g++ 的错误/限制?

4

2 回答 2

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++ 就是这样做的)。

于 2012-08-18T18:58:03.583 回答
0

这个问题听起来是由内而外的。您定义一个类型,std::function用于描述您将如何调用该类型的对象以及它们的返回值是什么。然后,您可以使用该特殊化std::function来包装具有不同参数类型或不同返回类型的各种可调用对象,包括 lambda。

于 2012-08-18T19:19:43.137 回答