How to deduce (possibly void) return type of member function?
If I have a class... struct X { int f(double x); void f(int y); }; ... and a template Y that wants to deduce the return-type of some member functions of T... template<class T> struct Y { typedef typename what_goes_here<T>::type f_double_return_type; typedef typename what_goes here<T>::type f_int_return_type; }; I"ve tried using... typedef BOOST_TYPEOF_TPL(static_cast<X*>(0)->f(double(0))) f_double_type; // this works ... but ... typedef BOOST_TYPEOF_TPL(static_cast<X*>(0)->f(int(0)) f_int_type; // does not work for "void" Of course, I wouldn't know which one returns "void" or not ahead of time. terry
Hi Terry, Terry Golubiewski schrieb:
If I have a class...
struct X { int f(double x); void f(int y); };
.... and a template Y that wants to deduce the return-type of some member functions of T...
template<class T> struct Y { typedef typename what_goes_here<T>::type f_double_return_type; typedef typename what_goes here<T>::type f_int_return_type; };
you should use boost::result_of to do such of things. See http://www.boost.org/doc/libs/1_43_0/libs/utility/utility.htm#result_of . Here a description. The class template |result_of| helps determine the type of a call expression. Given an lvalue |f| of type |F| and lvalues |t1|, |t2|, ..., |t/N/| of types |T1|, |T2|, ..., |T/N/|, respectively, the type |result_of<F(T1, T2, ..., T/N/)>::type| defines the result type of the expression |f(t1, t2, ...,t/N/)|. The implementation permits the type |F| to be a function pointer, function reference, member function pointer, or class type. When |F| is a class type with a member type |result_type|, |result_of<F(T1, T2, ..., T/N/)>| is |F::result_type|. Otherwise, |result_of<F(T1, T2, ..., T/N/)>| is |F::result<F(T1, T2, ...., T/N/)>::type| when |/N/ > 0| or |void| when |/N/ = 0|. For additional information about |result_of|, see the C++ Library Technical Report, N1836 <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf>, or, for motivation and design rationale, the |result_of| proposal <http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html>. Kim
I"ve tried using...
typedef BOOST_TYPEOF_TPL(static_cast<X*>(0)->f(double(0))) f_double_type; // this works
.... but ...
typedef BOOST_TYPEOF_TPL(static_cast<X*>(0)->f(int(0)) f_int_type; // does not work for "void"
Of course, I wouldn't know which one returns "void" or not ahead of time.
terry
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
How? I read the docs you referenced (previously), but I did not see a concrete example. typedef typename boost::result_of< ...what goes here???... (double)>::type f_double_return_type; terry ----- Original Message ----- From: "Kim Kuen Tang" <kuentang@vodafone.de> Newsgroups: gmane.comp.lib.boost.user To: <boost-users@lists.boost.org> Sent: Saturday, May 22, 2010 10:15 AM Subject: Re: How to deduce (possibly void) return type of member function?
Hi Terry,
Terry Golubiewski schrieb:
If I have a class...
struct X { int f(double x); void f(int y); };
.... and a template Y that wants to deduce the return-type of some member functions of T...
template<class T> struct Y { typedef typename what_goes_here<T>::type f_double_return_type; typedef typename what_goes here<T>::type f_int_return_type; };
you should use boost::result_of to do such of things.
Terry Golubiewski schrieb:
How? I read the docs you referenced (previously), but I did not see a concrete example.
i thought it was straightforward, but looking into details it was not the right reference. =-O However, below is a solution which relies on BOOST_TYPEOF. BOOST_TYPEOF will have a problem if the return_type is void. So i replace it with mpl::void_.
typedef typename boost::result_of< ...what goes here???... (double)>::type f_double_return_type;
terry
HTH Kim # include <boost/mpl/assert.hpp> # include <boost/typeof/typeof.hpp> # include <boost/type_traits/is_same.hpp> # include <boost/mpl/if.hpp> # include <boost/mpl/void.hpp> struct X { int f(int) { return 1; } double f(double) { return 1.0; } void f(char) {} }; template<typename Param, typename return_type> typename boost::mpl::if_< boost::is_same<return_type,void> , boost::mpl::void_ , return_type
::type deduce_type(return_type (X::*)(Param));
typedef BOOST_TYPEOF(deduce_type<char>(&X::f)) void_; typedef BOOST_TYPEOF(deduce_type<int>(&X::f)) int_; typedef BOOST_TYPEOF(deduce_type<double>(&X::f)) double_; int main() { BOOST_MPL_ASSERT((boost::is_same<void_,boost::mpl::void_>)); BOOST_MPL_ASSERT((boost::is_same<int_,int>)); BOOST_MPL_ASSERT((boost::is_same<double_,double>)); return 0; }
Mr. Kim Kuen Tang, You are awesome! You approach worked! Thank you! However.... I want to detect the function return type of a user-supplied message handler. This non-generic version compiles and runs as expected. #include <boost/mpl/identity.hpp> #include <boost/typeof/typeof.hpp> #include <cstddef> struct MessageHandler1 { void f(const char*); }; // MessageHandler1 struct MessageHandler2 { int f(const char*); }; // MessageHandler2 template<class R, class T> boost::mpl::identity<R> TypeDeducer(R (T::*)(const char*)); typedef BOOST_TYPEOF(TypeDeducer(&MessageHandler1::f))::type Type1; typedef BOOST_TYPEOF(TypeDeducer(&MessageHandler2::f))::type Type2; #include <iostream> #include <iomanip> #include <typeinfo> using namespace std; int main() { cout << typeid(Type1).name() << endl; cout << typeid(Type2).name() << endl; } // main But this generic version doesn't compile... 1 #include <boost/mpl/identity.hpp> 2 #include <boost/typeof/typeof.hpp> 3 4 #include <cstddef> 5 6 struct MessageHandler1 { 7 void f(const char*); 8 }; // MessageHandler1 9 10 struct MessageHandler2 { 11 int f(const char*); 12 }; // MessageHandler2 13 14 template<class R, class T> 15 boost::mpl::identity<R> TypeDeducer(R (T::*)(const char*)); 16 17 template<class T> 18 struct GenericDeducer { 19 typedef BOOST_TYPEOF_TPL(TypeDeducer(&T::f))::type type; 20 }; // GenericDeducer 21 22 #include <iostream> 23 #include <iomanip> 24 #include <typeinfo> 25 26 using namespace std; 27 28 int main() { 29 cout << typeid(GenericDeducer<MessageHandler1>::type).name() << endl; 30 cout << typeid(GenericDeducer<MessageHandler2>::type).name() << endl; 31 } // main try3.cpp using native typeof try3.cpp(19) : error C2784: 'boost::mpl::identity<T> TypeDeducer(R (__thiscall T::* )(const char *))' : could not deduce template argument for 'R (__thiscall T::* )(const char *)' from 'T::f' try3.cpp(15) : see declaration of 'TypeDeducer' try3.cpp(20) : see reference to class template instantiation 'GenericDeducer<T>' being compiled
Hi Terry, Terry Golubiewski schrieb:
But this generic version doesn't compile...
what you want is a "lazy" version of BOOST_TYPEOF. By wrapping your expression into BOOST_TYPEOF_NESTED_TYPEDEF you will delay the calculation until you really need it. The code below compile and work as expected. HTH Kim # include <boost/mpl/identity.hpp> # include <boost/typeof/typeof.hpp> # include <cstddef> struct MessageHandler1 { void f(const char*); }; // MessageHandler1 struct MessageHandler2 { int f(const char*); }; // MessageHandler2 template<class T,class R> boost::mpl::identity<R> TypeDeducer(R (T::*)(const char*)); template<class X> struct GenericDeducer { BOOST_TYPEOF_NESTED_TYPEDEF_TPL(Lazy,TypeDeducer(&X::f)) typedef typename Lazy::type::type type; }; // GenericDeducer # include <iostream> # include <iomanip> # include <typeinfo> # include <boost/mpl/assert.hpp> # include <boost/type_traits/is_same.hpp> using namespace std; int main() { cout << typeid(GenericDeducer<MessageHandler1>::type).name() << endl; cout << typeid(GenericDeducer<MessageHandler2>::type).name() << endl; } // main
participants (2)
-
Kim Kuen Tang
-
Terry Golubiewski