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

时间:2012-08-18 18:48:24

标签: c++ lambda c++11 g++

  

可能重复:
  Disambiguating calls to functions taking std::functions
  Isn't the template argument (the signature) of std::function part of its type?

我想重载一个函数,以便可以使用各种不同的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)>)

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

2 个答案:

答案 0 :(得分: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 ++的最新版本就是这样)。

答案 1 :(得分:0)

问题从里到外听起来。您可以使用std::function定义类型来描述您将如何调用该类型的对象以及它们的返回值。然后,您可以使用std::function的专门化来包装具有不同参数类型或不同返回类型的各种可调用对象,包括lambdas。