有没有可能找出lambda的参数types和返回types?

给定一个lambda,是否有可能找出它的参数types和返回types? 如果是的话,怎么样?

基本上,我想lambda_traits可以用于以下方面:

 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 

背后的动机是,我想在接受lambda作为参数的函数模板中使用lambda_traits ,我需要知道它的参数types和函数内的返回types:

 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! //... } 

目前,我们可以假设lambda只需要一个参数。

最初,我试图使用std::function作为:

 template<typename T> A<T> f(std::function<bool(T)> fun) { return A<T>(fun); } f([](int){return true;}); //error 

但显然会给错误( ideone )。 所以我把它TLambda版本的函数模板,并且想在std::function内部构造std::function对象(如上所示)。

有趣的是,我刚刚写了一个function_traits实现,它基于专门研究C ++ 0x中的lambda模板 ,可以给出参数types。 这个问题的答案中所描述的技巧是使用lambda operator()decltype

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

虽然我不确定这是否严格符合标准,但ideone编译了以下代码:

 template< class > struct mem_type; template< class C, class T > struct mem_type< TC::* > { 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, "" ); } 

但是,这只提供了函数types,所以必须从中提取结果和参数types。 如果你可以使用boost::function_traitsresult_typearg1_type将达到目的。 由于ideone似乎不提供C ++ 11模式的提升,我不能发布实际的代码,对不起。

显示在@KennyTMs答案中的专业化方法可以扩展到涵盖所有情况,包括可变和可变lambdaexpression式:

 template <typename T> struct closure_traits : closure_traits<decltype(&T::operator())> {}; #define REM_CTOR(...) __VA_ARGS__ #define SPEC(cv, var, is_var) \ template <typename C, typename R, typename... Args> \ struct closure_traits<R (C::*) (Args... REM_CTOR var) cv> \ { \ using arity = std::integral_constant<std::size_t, sizeof...(Args) >; \ using is_variadic = std::integral_constant<bool, is_var>; \ using is_const = std::is_const<int cv>; \ \ using result_type = R; \ \ template <std::size_t i> \ using arg = typename std::tuple_element<i, std::tuple<Args...>>::type; \ }; SPEC(const, (,...), 1) SPEC(const, (), 0) SPEC(, (,...), 1) SPEC(, (), 0) 

演示

请注意,对于可变参数operator()不会调整参数。 相反,人们也可以考虑is_variadic