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
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