Basically what I want to do, is to make a function template, that takes any Callable (function type / lambda / Functor) and returns a lambda-taking-the-similar-args-list and returning the type of original's return type
#include <iostream>
int func(int a,float b) {
return a+b;
}
struct callable {
int operator() (int a, float b) {
return a+b;
}
};
template <typename RV, typename... Args>
auto getLambdaFromCallable(RV(&func)(Args...)) {
auto l = [&](Args... args) -> RV {
return func(args...);
};
return l;
}
int main() {
auto f = getLambdaFromCallable(func);
std::cout << f(1,2.f);
std::cout << " " << typeid(f).name();
auto f2 = getLambdaFromCallable(callable{}); // doesn't work
callable{}(1,2); // works
auto lambdaTest = [](int a, float b) -> int {
return a+b;
};
auto f3 = getLambdaFromCallable(lambdaTest);
}
You can change getLambdaFromCallable
to:
template <typename F>
auto getLambdaFromFunction(const F& func) {
auto l = [&](auto&&... args)
-> decltype(func(std::forward<decltype(args)>(args)...)) {
return func(std::forward<decltype(args)>(args)...);
};
return l;
}
The reasoning behind this is that since you cannot get an exhaustive list of argument you can call a function object with (there might be multiple overloads in the first place), you might as well use a generic lambda which accepts everything and forward it to the callable.
To elaborate more about how this works:
The auto&&...
part gets converted to a template argument list on the lambda's call operator.
F
is deduced to whatever you called the getLambdaFromFunction
with (without the const
and reference but that can be changed if needed).
decltype(args)
is just there to use std::forward
which in turn is there to correctly forward both lvalue and rvalue references, see std::forward for more details.
The generated lambda object will look like this:
template <typename F>
class generatedLambda
{
public:
template <typename... Args>
auto operator()(Args&&... args) -> decltype(func(std::forward<decltype(args)>(args)...))
{
return func(std::forward<decltype(args)>(args)...);
}
private:
F func;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With