Is it possible to figure out the parameter type and return type of a lambda?
c++, c++11, lambda, metaprogramming, traits
Solution
Funny, I've just written a `function_traits` implementation based on Specializing a template on a lambda in C++0x which can give the parameter types. The trick, as described in the answer in that question, is to use the `decltype` of the lambda's `operator()`.
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
// For generic types, directly use the result of the signature of its 'operator()'
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
enum { arity = sizeof...(Args) };
// arity is the number of arguments.
typedef ReturnType result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
// the i-th argument is equivalent to the i-th tuple element of a tuple
// composed of those arguments.
};
};
// test code below:
int main()
{
auto lambda = [](int i) { return long(i*10); };
typedef function_traits<decltype(lambda)> traits;
static_assert(std::is_same<long, traits::result_type>::value, "err");
static_assert(std::is_same<int, traits::arg<0>::type>::value, "err");
return 0;
}
Note that this solution does not work for generic lambda like `[](auto x) {}`.
Problem
Given a lambda, is it possible to figure out it's parameter type and return type? If yes, how? Basically, I want `lambda_traits` which can be used in following ways: ``` auto lambda = [](int i) { return long(i*10); }; lambda_traits<decltype(lambda)>::param_type i; //i should be int lambda_traits<decltype(lambda)>::return_type l; //l should be long ``` The motivation behind is that I want to use `lambda_traits` in a function template which accepts a lambda as argument, and I need to know it's parameter type and return type inside the function: ``` template<typename TLambda> void f(TLambda lambda) { typedef typename lambda_traits<TLambda>::param_type P; typedef typename lambda_traits<TLambda>::return_type R; std::function<R(P)> fun = lambda; //I want to do this! //... } ``` For the time being, we can assume that the lambda takes exactly one argument. Initially, I tried to work with `std::function` as: ``` template<typename T> A<T> f(std::function<bool(T)> fun) { return A<T>(fun); } f([](int){return true;}); //error ``` But it obviously would give error. So I changed it to `TLambda` version of the function template and want to construct the `std::function` object inside the function (as shown above).