Thursday, November 19, 2015

C++ lambda inheritance

I was thinking about if we are able to inherit from a C++ lambda (say, anonymous class)

My first try was like this, use a helper function to forward the lambda body and store that as an private member of a class. But this is a HAS-A relationship, not really inherited from the lambda.

#include <iostream>
#include <utility>

template<typename lambda>
class Foo {
  lambda _t;
  int x = 5566;

public:
  Foo(lambda &&t) : _t(std::forward<lambda>(t)) {
    std::cout << "Foo()" << std::endl;
  }

  ~Foo() {
    std::cout << "~Foo()" << std::endl;
  }

  void operator()(void) {
    _t(x);
  }

  void operator()(int x) {
    std::cout << "Foo(int): " << x << std::endl;
  }
};

template<typename lambda>
Foo<lambda> make_class(lambda &&t) {
  return { std::forward<lambda>(t) };
}


int main (void) {
  auto qq = make_class([](int x) -> void {
    std::cout << "operator(int): " << x << std::endl;
  });

  qq();
  qq(7788);

  return 0;
}


Foo()
operator(int): 5566
Foo(int): 7788
~Foo()



suhorngT improved this as a real inheritance:


#include <iostream>
#include <utility>

template<typename lambda>
class Foo : public lambda {

public:
    Foo(lambda &&t) : lambda(t) {
      std::cout << "Foo()" << std::endl;
    }

    ~Foo() {
      std::cout << "~Foo()" << std::endl;
    }
};

template<typename lambda>
Foo<lambda> make_class(lambda &&t) {
  return { std::forward<lambda>(t) };
}


int main (void) {
  auto qq = make_class([](int x) -> void {
    std::cout << "operator(int): " << x << std::endl;
  });

  qq(123);
  return 0;
}




Foo()
operator(int): 123
~Foo()

After that I took out the make_class helper, and use decltype instead, make the syntax much better.


#include <iostream>

template<typename... lambda>
class Bar : public lambda... {

public:
  Bar(lambda... l) : lambda(l)... {
    std::cout << "Bar()" << std::endl;
  }

  void foo(void) {
    std::cout << "foo()" << std::endl;
  }
};


int main(void)  {
  int a = 55;

  auto gg = [a](int b) -> void {
    std::cout << "operator(): " << a << b << std::endl;
  };

  auto qq = Bar<decltype(gg)>(gg);

  qq(66);
  qq.foo();

  return 0;
}



Bar()
operator(): 5566
foo()


Reference:
http://cpptruths.blogspot.tw/2014/05/fun-with-lambdas-c14-style-part-2.html
http://cpptruths.blogspot.com/2014/03/fun-with-lambdas-c14-style-part-1.html

No comments:

Post a Comment