Parametrlərin növünü və dönüş lambda növünü müəyyən etmək mümkündürmü?

Lambda verildiyində, parametrin növü və qaytarılma dəyərinin növü müəyyən edilə bilərmi? Əgər belədirsə, necə?

Əsasən lambda_traits , bu da aşağıdakı yollarla istifadə edilə bilər:

 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 

Motivasiya lambda_traits - lambda_traits bir lambda arqumentini bir arqument kimi qəbul edən bir funksiya şablonu içində istifadə lambda_traits və mən onun parametrinin növü və funksiyanın daxilində dönüş dəyərinin növü ilə tanış olmaq lazımdır:

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

İndiyə qədər, lambda tam olaraq bir arqument götürür.

Əvvəlcə std::function ilə çalışmağa çalışdım:

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

Ancaq bu açıq-aydın bir səhv ( ideone ) verəcəkdir . Buna görə funksiyanı şablonun TLambda versiyasına TLambdastd::function içərisində std::function obyekti yaratmaq istəyirəm (yuxarıda göstərildiyi kimi).

108
30 окт. 30 Oktyabrda Nawaz tərəfindən təyin olundu 2011-10-30 08:47 '11 'də 8:47' də 2011-10-30 08:47
@ 3 cavab

Funny, yalnız c ++ 0x-da lambda üzrə ixtisaslaşmış bir model əsasında parametrlər növlərini verə bilən bir function_traits tətbiqini yazdım. Bu sualın cavabında təsvir edilən hiylə, decltype lambda operator() istifadə etməkdir.

 template <typename T> struct function_traits : public function_traits<decltype( {}; // 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; } 
130
30 окт. Cavab 30 ay sonra kennytm verilir . 2011-10-30 10:27 '11 saat 10:27 'da 2011-10-30 10:27

Bu dəqiq bir standart oyun olduğundan əmin deyiləmsə də, ideone aşağıdakı kodu tərtib etdi:

 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(  ) >::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, "" ); } 
border=0

Lakin, bu yalnız funksiyanın növünü təmin edir, beləliklə nəticə və parametr növlərindən çıxarılmalıdır. boost::function_traits istifadə edə bilərsiniz, result_typearg1_type hədəfə uyğun gəlir. Ideon C ++ 11 rejimində genişləndirməyi təmin etmirsə, mən faktiki kodu dərc edə bilmərik, üzr istəyirəm.

10
30 окт. Cavab Ise Wisteria 30 oct verilir. 2011-10-30 10:17 '11 at 10:17 'da 2011-10-30 10:17

@KennyTM cavabında göstərilən ixtisaslaşma üsulu dəyişkən və dəyişkən lambdalar da daxil olmaqla bütün halları əhatə etmək üçün genişləndirilə bilər:

 template <typename T> struct closure_traits : closure_traits<decltype( {}; #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) 

Demo .

Aritenin operator() s dəyişənləri üçün konfiqurasiya edilmədiyini unutmayın. Alternativ olaraq, siz də is_variadic hesab edə bilərsiniz.

5
29 янв. Cavab Columbo Jan 29 tərəfindən verilir 2015-01-29 14:35 '15 'da 14:35' de 2015-01-29 14:35