Is it possible to figure out the parameter type and return type of a lambda?
Though I'm not sure this is strictly standard conforming, ideone compiled the following code:
template< class > struct mem_type;
template< class C, class T > struct mem_type< T C::* > {
typedef T type;
};
template< class T > struct lambda_func_type {
typedef typename mem_type< decltype( &T::operator() ) >::type type;
};
int main() {
auto l = [](int i) { return long(i); };
typedef lambda_func_type< decltype(l) >::type T;
static_assert( std::is_same< T, long( int )const >::value, "" );
}
However, this provides only the function type, so the result and parameter
types have to be extracted from it.
If you can use boost::function_traits
, result_type
and arg1_type
will meet the purpose.
Since ideone seems not to provide boost in C++11 mode, I couldn't post
the actual code, sorry.
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) {}
.