Iterate over template arguments

Hi, I have a set of old classes which I use for inter process communication: Example: template<typename T0, typename T1> class Interface2: public InterfaceBase { public: Interface2( const std::string & name, IPCManager * ipcmanager) : InterfaceBase(name, ipcmanager){ } Interface2( const std::string & name, boost::function<void ( const T0 & t0, const T1 & t1 ) > _f, IPCManager * ipcmanager) : InterfaceBase(name, ipcmanager), f(_f) { } virtual ~Interface2() { } boost::function<void ( const T0 & t0, const T1 & t1 ) > f; protected: void handler(IpcMsg & m) { if(! f.empty()){ if( m.value_size() != 2 ) { m.set_type(IpcMsg_Type_RESPONSE_FAILED_WRONG_VALUE_NUMBERS); return; } GMB_ARGUMENT_DESERILIZE(T0, 0); GMB_ARGUMENT_DESERILIZE(T1, 1); try { f(t0, t1); m.set_type(IpcMsg_Type_RESPONSE_OK); } catch (std::exception e) { m.set_type(IpcMsg_Type_RESPONSE_FAILED_EXCEPTION); } }else{ m.set_type(IpcMsg_Type_RESPONSE_FAILED_NO_FUNCTION_ATTACHED); } } IPCManager * ipc; }; It works fine, but it might not be the most elegant solution, and I would very much like to improve it. Today I have Interface0-10 which accept from 0 to 10 arguments, and InterfaceCaller0-10 which call an interface with 0-10 arguments. And another set of classes with an return value as well. What I would like is an interface where the following would be valid (much like boost function): Interface< int (int, std::string ) > if1(...) ; I known this might not be easy or the intension of c++99, but I would like to give it a try anyway... So, I would appreciate it if somebody could give me some pointers on how I can process each of the templates arguments. I do not have access to a c++0x compiler on the target where this is used. Best regards Allan W. Nielsen

On 11/23/2011 03:34 PM, Allan Nielsen wrote:
What I would like is an interface where the following would be valid (much like boost function):
Interface< int (int, std::string )> if1(...) ;
I known this might not be easy or the intension of c++99, but I would like to give it a try anyway...
There is no particular problem doing that in C++98/03. You may want to take a look at <http://www.boost.org/doc/libs/release/libs/function_types/doc/html/index.html> It can extract the return type and convert the arguments to an MPL sequence.

On Wed, Nov 23, 2011 at 8:45 AM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
On 11/23/2011 03:34 PM, Allan Nielsen wrote:
What I would like is an interface where the following would be valid (much like boost function):
Interface< int (int, std::string )> if1(...) ;
You may want to take a look at <http://www.boost.org/doc/libs/release/libs/function_types/doc/html/index.html>
It can extract the return type and convert the arguments to an MPL sequence.
I'm in the process of trying to wrap my head around MPL and am reading the metaprogramming book. It has a good description of MPL sequences and iterating over arguments in either ch 3 or 4 (that's from memory...too lazy to pull up the book). -- Chris Cleeland

On Wed, Nov 23, 2011 at 3:45 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
On 11/23/2011 03:34 PM, Allan Nielsen wrote:
What I would like is an interface where the following would be valid (much like boost function):
Interface< int (int, std::string )> if1(...) ;
I known this might not be easy or the intension of c++99, but I would like to give it a try anyway...
There is no particular problem doing that in C++98/03.
You may want to take a look at <http://www.boost.org/doc/libs/release/libs/function_types/doc/html/index.html>
It can extract the return type and convert the arguments to an MPL sequence.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Hi It might be me which does not understand it, but as I read the documentation funciton_types is for manipulating functions pointers, not to manage template arguments... Please correct me if I'm wrong -- Allan

It might be me which does not understand it, but as I read the documentation funciton_types is for manipulating functions pointers, not to manage template arguments...
Please correct me if I'm wrong Okay, I got it... <int(int)> is one template argument... : typename boost::function_types::result_type<T0>::type is the return type, and I can use parameter_types and MPL to iterate over the parameters. Clever..
But how do I implement the call interface: template<typename T > struct IfCall { typedef typename boost::function_types::result_type<T0>::type R; R call( /* T0, T1, T2...*/ ) { // can I get the MPL sequence into the method signature?? } }; -- Allan

On Wed, Nov 23, 2011 at 7:33 AM, Allan Nielsen <a@awn.dk> wrote:
It might be me which does not understand it, but as I read the documentation funciton_types is for manipulating functions pointers, not to manage template arguments...
Please correct me if I'm wrong Okay, I got it... <int(int)> is one template argument... : typename boost::function_types::result_type<T0>::type is the return type, and I can use parameter_types and MPL to iterate over the parameters. Clever..
But how do I implement the call interface:
template<typename T > struct IfCall { typedef typename boost::function_types::result_type<T0>::type R;
R call( /* T0, T1, T2...*/ ) { // can I get the MPL sequence into the method signature?? } };
Ugh. Well, what I can think of at the moment: - Use the Boost.Preprocessor library to specialize each arity of lfCall, e.g., generate template< class R, class T0 > struct lfCall< R ( T0 ) > { /*...*/ R call(T0) { /*...*/ } }; and similarly for all other supported arities with the preprocessor; or - If you're flexible in the call interface, you might be able to utilize Boost.Fusion's fuse/unfuse adaptors [1]. - Jeff http://www.boost.org/doc/libs/1_48_0/libs/fusion/doc/html/fusion/functional/...

On 11/23/2011 04:33 PM, Allan Nielsen wrote:
It might be me which does not understand it, but as I read the documentation funciton_types is for manipulating functions pointers, not to manage template arguments...
Please correct me if I'm wrong Okay, I got it...<int(int)> is one template argument... : typename boost::function_types::result_type<T0>::type is the return type, and I can use parameter_types and MPL to iterate over the parameters. Clever..
But how do I implement the call interface:
template<typename T> struct IfCall { typedef typename boost::function_types::result_type<T0>::type R;
R call( /* T0, T1, T2...*/ ) { // can I get the MPL sequence into the method signature?? } };
You need to use the preprocessor for this; in that case, you can also get rid of Boost.FunctionTypes. #include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_binary_params.hpp> #include <boost/preprocessor/punctuation/comma_if.hpp> #define IFCALL_MAX_ARITY 5 template<class Sig> struct IfCall; #define M0(z, n, t) \ template<class R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A)>\ struct IfCall<R(BOOST_PP_ENUM_PARAMS(n, A))> \ { \ R call(BOOST_PP_ENUM_BINARY_PARAMS(n, A, const& a)) \ { \ return R(); \ } \ }; \ /**/ BOOST_PP_REPEAT(BOOST_PP_INC(IFCALL_MAX_ARITY), M0, ~) #undef M0
participants (4)
-
Allan Nielsen
-
Chris Cleeland
-
Jeffrey Lee Hellrung, Jr.
-
Mathias Gaunard