0

我有一个重载函数,具有以下签名:

void Foo(const std::function<void(int     )> &func);
void Foo(const std::function<void(int, int)> &func);

当我想将 Foo() 与 lambdas 一起使用时,我必须执行以下操作:

Foo((std::function<void(int     )>) [] (int i       ) { /* do something */ });
Foo((std::function<void(int, int)>) [] (int i, int j) { /* do something */ });

两者都不是那么用户友好。使用该函数会容易得多,而不必在 lambdas 之前添加强制转换 "(std::function<...>)" - 如下所示:

    Foo([] (int i       ) { /* do something */ }); // executes the 1st Foo()
    Foo([] (int i, int j) { /* do something */ }); // executes the 2nd Foo()

所以,我需要另一个重载,它接受 lambda 作为其参数,并自动将 lambda 转换为上述签名之一。如何才能做到这一点?或者,一开始有可能吗?

template <typename Function> void Foo(Function function) {
    // insert code here: should be something like
    //   - check the signature of the 'function'; and
    //   - call 'Foo()' corresponding to the signature
}

请帮忙。

PS。我正在使用VS2010。

4

2 回答 2

3

如果你的 lambda 没有捕获任何变量——也就是说,它以——开头,[]那么它可以转换为函数指针,你可以Foo像这样声明:

void Foo(void(*func)(int));
void Foo(void(*func)(int, int));

如果您想保留这些std::function版本,您可以将这些版本转发给那个版本。如果您不想单独实现它们,我认为可变参数模板会做得很好:

template<class... Args>
void Foo(void(*func)(Args...)) {
    return std::function<void(Args...)>(func);
}

如果您的 lambdas 捕获变量,那么它们不能转换为函数指针,您需要自己将它们包装起来std::function

于 2013-04-09T05:41:38.013 回答
1

Lambda 隐式转换为 std::function<>,不需要显式转换。

std::function<void(int, int)> func = [](int a, int b){ printf("Hello Lambda world!"); };
func(1, 2);

啊,您正试图获得对它的 const 引用。为什么呢?最好使用右手参考(因为它是临时的)或副本。在这两种情况下,它也应该隐式转换......

于 2013-04-09T06:19:02.287 回答