How to inherit from lambdas?


What happens behind the scene when lambda is created:

auto fun = [](int num) { return num; };

C++ Insights can be used to see what is going on behind the scene:

class __lambda_1_12
{
  public: 
  inline /*constexpr */ int operator()(int num) const
  {
    return num;
  }

  using retType_1_12 = int (*)(int);
  inline /*constexpr */ operator retType_1_12 () const noexcept
  {
    return __invoke;
  };

  private: 
  static inline int __invoke(int num)
  {
    return num;
  }
};

__lambda_1_12 fun = __lambda_1_12{};

This tells us that lambdas are standard types, and that actually we can inherit from them.

template <typename L1, typename L2>
struct Combo : L1, L2 {
  Combo(L1 l1, L2 l2) : L1(std::move(l1)), L2(std::move(l2)) {}
  using L1::operator();
  using L2::operator();
};

Let’s create two lambdas:

auto l1 = []{return 42;};
auto l2 = [](const int n){ return n*n;}

When instantiating Combo we will take advantage of Class Template Argument Deduction from C++17

Combo combo(l1, l2);
std::cout << combo() << std::endl;
std::cout << combo(3) << std::endl;

A more generic version can be created and used as

template <typename... Ls>
struct Combo : Ls... {
  Combo(Ls... ls) : Ls(std::move(ls))... {}
  using Ls::operator()...;
};
auto l1 = [] { return 42; };
auto l2 = [](const int n) { return n * n; };
auto l3 = [](const int n, int m) { return n * m; };

Combo combo(l1, l2, l3, [](const std::string& s){return s + " " + s;});
std::cout << combo() << std::endl;
std::cout << combo(3) << std::endl;
std::cout << combo(3, 43) << std::endl;
std::cout << combo("cpp") << std::endl;

First version: https://godbolt.org/z/TWs3e8raY

Second version: https://godbolt.org/z/7qvchhvzx

Join the discussion

comments powered by Disqus