如何立即调用C ++ lambda?

时间:2017-07-02 07:19:50

标签: c++ c++11 lambda c++14

I类继承的构造函数需要传入一个非平凡的对象。与此类似:

MyFoo::MyFoo() : SomeBase( complexstuff )
{
    return;
}

complexstuffMyFoo几乎没有关系,因此我不想将其传入。

我没有写一些返回complexstuff的1-off临时函数,而是使用了lambda。我花了几分钟才弄明白的是我必须调用 lambda。所以我的代码现在看起来像这样:

MyFoo::MyFoo() : SomeBase(
    []()
    {
        /* blah blah do stuff with complexstuff */
        return complexstuff;
    } () )
{
    return;
}

如果你没有抓住它,那就很微妙了。但是在lambda体之后,我不得不把()告诉编译器立即"运行" lambda。在弄清楚我做错了什么之后才有意义。否则,如果没有()来调用lambda,gcc就会说出类似的内容:

error: no matching function for call to 'SomeBase(<lambda()>)'

但现在我有想法 - 我这样做了吗?在C ++ 11或C ++ 14中是否有更好的方法告诉编译器我希望它立即调用我写的lambda?或者添加一个空的(),就像我按照通常的方式做到这一点?

4 个答案:

答案 0 :(得分:12)

  

但现在我想到了 - 我是否正确地做到了这一点?

是的,你做到了。

  

在C ++ 11或C ++ 14中是否有更好的方法告诉编译器我希望它立即调用我编写的lambda?

不是我知道的。 lambda也只是一个函数对象,所以你需要()来调用它,没有办法解决它(当然除了一些调用lambda的函数,如{{ 1}})。

如果需要,可以在捕获列表后删除std::invoke,因为lambda不接受任何参数。

  

或者添加一个空(),就像我按照通常的方式做到这一点?

是的,这是最短的路。如前所述,()也会起作用,但需要更多输入。我会说用std::invoke进行直接调用是通常的做法。

答案 1 :(得分:4)

没有办法告诉编译器立即调用lambda。最简单的课程(在复杂性和打字字符数量方面)就是你已经做过的。对于那些使用过具有闭包语言的人来说,这也非常惯用(我在这里思考JavaScript)。

如果您想避免语法,请修改SomeBasecomplexstuff以执行可调用。

如果您想要的只是用于调用lambda的语法糖,您可以随时执行像Alexandrescu的SCOPE_GUARD那样的操作,并滥用运算符重载:

Live example

#include <iostream>

constexpr enum {} invoke{};

template<class Callable>
auto operator+(decltype(invoke) const&, Callable c) -> decltype(c()) {
    return c();
}


int main() {
    invoke + []() {
        std::cout << "called";
    };
}

但我不会。发明自己的DSL只会让你的代码更糟糕。坚持使用简单语言结构的习语。

答案 2 :(得分:4)

在C ++ 17中,您可以使用std::invoke。这与你做的完全相同,但也许你会发现这个更清楚。

#include <iostream>
#include <functional>

void foo(int i)
{
  std::cout << i << '\n';
}

int main()
{
  foo( std::invoke( []() { return 1; } ) );
}

答案 3 :(得分:2)

  

有没有更好的方式

您还可以考虑使用构建complexstuff的私有静态成员函数,例如

class MyFoo : public Base {
private:
    static SomeComplexType compute_complex_stuff() {
      SomeComplexType complexstuff;
      /*compute the complexstuff */
      return complexstuff;
    };
public: 
    MyFoo() : Base(compute_complex_stuff()) {};
};

我不知道它是否比定义一个lambda表达式并立即应用它更好;这是恕我直言的品味;对于一个 short lambda体,我更喜欢立即应用一个lambda表达式(但是在这种情况下,某些编译器可能会创建临时闭包,所以没有优化它可能会更慢;我期望大多数C ++ 11编译器能够进行优化。)

BTW,GCC为您的目的提供statement expression语言扩展(Clang也理解)。有了它,你可以写

MyFoo::MyFoo : Base (({
  SomeComplexType complexstuff;
  /*compute the complexstuff */
  return complexstuff;
}) {};