Discovering C++11 lambda argument and result types to construct boost::function

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi! On comp.lang.c++.moderated I talked to Daniel Krügler about how to discover argument and result types from C++11 lambdas in a template context. The thread has the title "How to discover argument and result types from lambda for constructing std::function?" https://groups.google.com/d/topic/comp.lang.c++.moderated/qaMECIUlJp0/discus... The task is to provide a function template "make_function" that takes a C++11 lambda expression and returns a boost::function with the correct signature to call the lambda. This may be extended to accept any other callable type. Is there such a thing already in Boost? I'd like to add it. Would it go to Boost.Function alone? Or would parts fit into TypeTraits? Does Doug still maintain Boost.Function? Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG/MacGPG2 v2.0.17 (Darwin) Comment: GPGTools - http://gpgtools.org Comment: keyserver x-hkp://pool.sks-keyservers.net iEYEARECAAYFAk80RsMACgkQhAOUmAZhnmr5gACdGI6q9Xi1SbtpHs23GlAhU9uu Y3kAnjCpiZFGJp+IpnFVS3gmtZOqZp42 =GGdI -----END PGP SIGNATURE-----

On 02/09/2012 11:20 PM, Frank Birbacher wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Hi!
On comp.lang.c++.moderated I talked to Daniel Krügler about how to discover argument and result types from C++11 lambdas in a template context. The thread has the title "How to discover argument and result types from lambda for constructing std::function?"
https://groups.google.com/d/topic/comp.lang.c++.moderated/qaMECIUlJp0/discus...
The task is to provide a function template "make_function" that takes a C++11 lambda expression and returns a boost::function with the correct signature to call the lambda. This may be extended to accept any other callable type.
Is there such a thing already in Boost? I'd like to add it. Would it go to Boost.Function alone? Or would parts fit into TypeTraits? Does Doug still maintain Boost.Function?
I think you should just do a meta-function that gives the function type that matches a given lambda. No need to put boost::function in the loop at all. Once you have your function type, you can directly use it as an argument to boost::function, std::function, or whatever other compatible template.

On 02/12/2012 05:15 PM, Mathias Gaunard wrote:
On 02/09/2012 11:20 PM, Frank Birbacher wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Hi!
On comp.lang.c++.moderated I talked to Daniel Krügler about how to discover argument and result types from C++11 lambdas in a template context. The thread has the title "How to discover argument and result types from lambda for constructing std::function?"
https://groups.google.com/d/topic/comp.lang.c++.moderated/qaMECIUlJp0/discus...
The task is to provide a function template "make_function" that takes a C++11 lambda expression and returns a boost::function with the correct signature to call the lambda. This may be extended to accept any other callable type.
Is there such a thing already in Boost? I'd like to add it. Would it go to Boost.Function alone? Or would parts fit into TypeTraits? Does Doug still maintain Boost.Function?
I think you should just do a meta-function that gives the function type that matches a given lambda.
And that meta-function is just template<class F> struct function_type : remove_pointer<decltype(&F::operator())> { };

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi! Am 12.02.12 17:37, schrieb Mathias Gaunard:
And that meta-function is just
template<class F> struct function_type : remove_pointer<decltype(&F::operator())> { };
Well, that does not work for the following reason (example code below): "The same type as T, but with any pointer modifier removed. Note that pointers to members are left unchanged: removing the pointer decoration would result in an invalid type." (see: http://www.boost.org/doc/libs/1_48_0/libs/type_traits/doc/html/boost_typetra... ) So this is the point: I need a signature from a member function. There is no type trait that does this. Any other suggestions? Frank //////////// EXAMPLE: #include <type_traits> #include <utility> #include <boost/function.hpp> using boost::function; template<typename F> struct function_type { typedef typename std::remove_pointer< decltype(&F::operator()) >::type signature; typedef function<signature> type; }; template<typename F> typename function_type<F>::type make_function(F && f) { typedef typename function_type<F>::type result_type; return result_type(std::forward<F>(f)); } int main() { auto a = make_function([](int){ return 4; }); } //////////// OUTPUT GCC 4.6: MainTest.cpp:26:45: error: invalid use of incomplete type 'function_type<main()::<lambda(int)> >::type {aka struct boost::function<int (main()::<lambda(int)>::*)(int)const> }' function_fwd.hpp:33:38: error: declaration of 'function_type<main()::<lambda(int)> >::type {aka struct boost::function<int (main()::<lambda(int)>::*)(int)const>}' MainTest.cpp:26:45: error: unable to deduce 'auto' from '<expression error>' -----BEGIN PGP SIGNATURE----- Version: GnuPG/MacGPG2 v2.0.17 (Darwin) Comment: GPGTools - http://gpgtools.org Comment: keyserver x-hkp://pool.sks-keyservers.net iEYEARECAAYFAk85X7IACgkQhAOUmAZhnmpyDQCfdZ8860I/iuZZ1UE2zP07Bfq8 xToAn0g0cwkxFYWNk+SRlTDIyr97MZup =4eow -----END PGP SIGNATURE-----

On Mon, Feb 13, 2012 at 11:08 AM, Frank Birbacher <bloodymir.crap@gmx.net>wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Hi!
Am 12.02.12 17:37, schrieb Mathias Gaunard:
And that meta-function is just
template<class F> struct function_type : remove_pointer<decltype(&F::operator())> { };
Well, that does not work for the following reason (example code below):
"The same type as T, but with any pointer modifier removed. Note that pointers to members are left unchanged: removing the pointer decoration would result in an invalid type." (see:
http://www.boost.org/doc/libs/1_48_0/libs/type_traits/doc/html/boost_typetra... )
So this is the point: I need a signature from a member function. There is no type trait that does this. Any other suggestions?
[...] Boost.FunctionTypes + Boost.MPL? Something like typename boost::function_types::function_type< typename boost::mpl::push_front< typename boost::function_types::result_type<F>::type, typename boost::mpl::pop_front< typename boost::function_types::parameter_types<F>::type >::type >::type
::type
or define a metafunction that converts a pointer-to-member-function type to the desired function type for some spectrum of arities: template< class F > struct member_function_to_function; template< class R, class T > struct member_function_to_function< R (T::*)()
{ typedef R type(); }; template< class R, class T > struct member_function_to_function< R (T::*)() const > { typedef R type(); }; // etc...up to some maximum arity
- Jeff

On Mon, 13 Feb 2012 20:08:34 +0100, Frank Birbacher <bloodymir.crap@gmx.net> wrote:
So this is the point: I need a signature from a member function. There is no type trait that does this. Any other suggestions?
The code example below compiles and runs nicely with gcc 4.7. A note: if you substitute using signature = R (Arg...); with: typedef R (Arg...) signature; you get a compile time error. Cheers, -- Marco #include <iostream> #include <utility> #include <boost/function.hpp> using boost::function; ////////////////////////////////////////////////////////////// // member function traits template<typename MembFuncPtr> struct memb_func_traits {}; template< typename ClassT, typename R, typename... Arg> struct memb_func_traits<R ClassT::* (Arg...)> { using class_type = ClassT; using signature = R (Arg...); }; template< typename ClassT, typename R, typename... Arg> struct memb_func_traits<R (ClassT::*) (Arg...) const> { using class_type = ClassT; using signature = R (Arg...); }; template<typename F> struct function_type { typedef typename memb_func_traits< decltype(&F::operator()) >::signature signature; typedef function<signature> type; }; template<typename F> typename function_type<F>::type make_function(F && f) { typedef typename function_type<F>::type result_type; return result_type(std::forward<F>(f)); } int main() { auto a = make_function([](int){ return 4; }); assert( a(1) == 4 ); std::cout << a(1) << std::endl; } -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

A note: if you substitute using signature = R (Arg...); with: typedef R (Arg...) signature; you get a compile time error.
I believe the correct typedef syntax is: typedef R signature(Arg...); (This syntax never made sense to me, but it's the only one there was prior to C++11). Regards, Nate

On Mon, 13 Feb 2012 23:25:51 +0100, Nathan Ridge <zeratul976@hotmail.com> wrote:
A note: if you substitute using signature = R (Arg...); with: typedef R (Arg...) signature; you get a compile time error.
I believe the correct typedef syntax is:
typedef R signature(Arg...);
(This syntax never made sense to me, but it's the only one there was prior to C++11).
Right! A stupid error! Thanks for having pointed out that. I prefer the new using syntax, too. Regards, -- Marco -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

From: zeratul976@hotmail.com Date: Mon, 13 Feb 2012 22:25:51 +0000
A note: if you substitute using signature = R (Arg...); with: typedef R (Arg...) signature; you get a compile time error.
I believe the correct typedef syntax is:
typedef R signature(Arg...);
(This syntax never made sense to me, but it's the only one there was prior to C++11).
"signature" goes in the same place a function name would go. The inventors of C copiedthe "declaration the same as usage" syntax from B(PCL). I warned about making your programming syntax cute; it looks magnificent at first glance,but months later (or sooner) people discover ways the cuteness backfires. (Seestd::vector<bool>.) When I found out (a few months ago) how C got its declaration syntax,I realized that C and C++ programmers have been slammed for decades(!) over the inventor ofB being cute! Daryle W.
participants (6)
-
Daryle Walker
-
Frank Birbacher
-
Jeffrey Lee Hellrung, Jr.
-
Marco Cecchetti
-
Mathias Gaunard
-
Nathan Ridge