【问题标题】:C++ Functions with lambdas as arguments以 lambda 作为参数的 C++ 函数
【发布时间】:2013-04-09 14:49:07
【问题描述】:

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

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

当我想将 Foo() 与 lambda 一起使用时,我必须这样做:

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
}

请帮忙。

附言。我用的是VS2010。

【问题讨论】:

  • 您使用的是什么编译器,什么版本?顺便说一句,在 clang 3.3(主干 177501)中工作正常。

标签: c++ lambda


【解决方案1】:

如果您的 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);
}

如果您的 lambda 捕获变量,则它们不能转换为函数指针,您需要自己将它们包装在 std::function 中。

【讨论】:

  • 对不起,我没有提到我使用的是 VS2010,它不允许 lambda-to-function-pointer 转换。我想我将不得不更改我的编译器或使用它......非常感谢!
【解决方案2】:

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

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

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

【讨论】: