C++ lambda returning itself

2019-04-23 01:12发布

问题:

I wanted to write a lambda that returns itself, so I could call it multiple times on the spot. But it looks like inside of a lambda this refers not to the lambda but to the surrounding object's this, if the lambda is defines inside a member function.

Here's an example:

#include <iostream>

int main(int argc, char* argv[]) {
  int a = 5;
  [&](int b) {
    std::cout << (a + b) << std::endl;
    return *this;
  }(4)(6);
}

Is there a way to do something comparable?

回答1:

With old functor:

int main() {
  int a = 5;
  struct S {
    const S& operator ()(int b) const {
      std::cout << (a + b) << std::endl;
      return *this;
    }
    const int& a;
  };
  S{a}(4)(6);
}

Demo



回答2:

You cant return the lambda itself, but you can return a different one:

#include <iostream>

int main() {
  int a = 5;    
  [&](int b) {
      auto impl = [&](int b){std::cout << (a + b) << std::endl;};
      impl(b);
      return impl;
  }(4)(6);
}

However, this allows only to call it one more time. Not sure if there is some trick to get more out of it...



回答3:

Ben Voigt proposes to use Y combinators (which are a great proposal to the standard library, BTW), but your problem is simpler. You can introduce a small template functor that will be called instead of the lambda:

template<typename T>
struct recallable_impl {
    template<typename... Args>
    recallable_impl& operator()(Args&&... args) {
        f(std::forward<Args>(args)...);
        return *this;
    }

    template<typename F>
    recallable_impl(F&& f)
      :  f{std::forward<F>(f)}
    {}
private:
    T f;
};

template<typename T>
decltype(auto) recallable(T&& f) {
    return recallable_impl<std::decay_t<T>>(std::forward<T>(f));
}

Your lambda will then not even need to explicitly return anything:

int main() {
  int a = 5;  
  recallable([&](int b){std::cout << (a + b) << std::endl;})(4)(5)(6)(7)(8);
}


回答4:

You can call a lambda if you assign it to a predifned type (not auto), and it gets captured:

std::function<void(int)> f =[&f](int n)
{
    if (n>0) f(n-1);
    return;
};


标签: c++ lambda