Help with Boost Preprocessor

Let's say I have a class template functor like this: struct func { typedef void result_type; template <class A1,class A2,class A3> void operator()( A1, A2, A3, int x ) { } }; Given a list of types, I want the function instantiated and called for all permutations of the types in the list; the additional argument(s), x, just need to be forwarded the same for all instances. Actually I got it working, see http://codepad.org/tnYTy9Iw. I don't think that my solution is very good though. First, it has some run-time overhead due to the use of boost::bind in fwd1 and fwd2 (see link above.) Second, I'd like the macro that defines the type list not to be hard-coded in fwd1 and fwd2. Is this possible? Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

AMDG Emil Dotchevski wrote:
Let's say I have a class template functor like this:
struct func { typedef void result_type;
template <class A1,class A2,class A3> void operator()( A1, A2, A3, int x ) { } };
Given a list of types, I want the function instantiated and called for all permutations of the types in the list; the additional argument(s), x, just need to be forwarded the same for all instances.
Actually I got it working, see http://codepad.org/tnYTy9Iw.
I don't think that my solution is very good though. First, it has some run-time overhead due to the use of boost::bind in fwd1 and fwd2 (see link above.) Second, I'd like the macro that defines the type list not to be hard-coded in fwd1 and fwd2.
Is this possible?
So to be clear given the sequence int, long, you'd like to generate func()(int(), int(), int()); func()(int(), int(), long()); func()(int(), long(), int()); func()(int(), long(), long()); func()(long(), int(), int()); func()(long(), int(), long()); func()(long(), long(), int()); func()(long(), long(), long()); In Christ, Steven Watanabe

AMDG Emil Dotchevski wrote:
Let's say I have a class template functor like this:
struct func { typedef void result_type;
template <class A1,class A2,class A3> void operator()( A1, A2, A3, int x ) { } };
Given a list of types, I want the function instantiated and called for all permutations of the types in the list; the additional argument(s), x, just need to be forwarded the same for all instances.
Actually I got it working, see http://codepad.org/tnYTy9Iw.
I don't think that my solution is very good though. First, it has some run-time overhead due to the use of boost::bind in fwd1 and fwd2 (see link above.) Second, I'd like the macro that defines the type list not to be hard-coded in fwd1 and fwd2.
Is this possible?
How does this work #include <boost/preprocessor/seq/for_each_product.hpp> #include <boost/preprocessor/seq/transform.hpp> #include <boost/preprocessor/seq/enum.hpp> #include <iostream> struct func { typedef void result_type; template <class A1,class A2,class A3> void operator()( A1, A2, A3, int x ) { std::cout << typeid(A1).name() << ',' << typeid(A2).name() << ',' << typeid(A3).name() << ',' << x << '\n'; } }; template<class T> T make() { return T(); } #define CALL_FUNC(r, args) func()(BOOST_PP_SEQ_ENUM(args), x); #define MAKE_OBJECT(s, data, elem) make<elem>() #define FUNC_II(types) \ BOOST_PP_SEQ_FOR_EACH_PRODUCT(CALL_FUNC, (types)(types)(types)) #define FUNC_I(types) FUNC_II(types) #define FUNC(types, arg) \ if(true) { \ int x = arg; \ FUNC_I(BOOST_PP_SEQ_TRANSFORM(MAKE_OBJECT, ~, types)) \ } else ((void)0) int main() { FUNC((int)(long), 42); } In Christ, Steven Watanabe

Steven, thanks for your reply. It is too late for me right now to understand your solution, but at first look it seems like it's very close to what I need but not quite. :) The interface I need is something like: CALL_PROD3(boost::bind(func(),_1,_2,_3,42),TYPE_LIST) I do want to use bind (so I can pass any number of additional arguments to the function), and I don't want the function name or the type list macro name to be hard-coded. I just don't like the *nested* use of bind in the solution I posted, and the fact that the type list macro name is hard-coded in the helper functions fwd1 and fwd2. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode On Sat, Aug 29, 2009 at 6:34 PM, Steven Watanabe<watanabesj@gmail.com> wrote:
AMDG
Emil Dotchevski wrote:
Let's say I have a class template functor like this:
struct func { typedef void result_type;
template <class A1,class A2,class A3> void operator()( A1, A2, A3, int x ) { } };
Given a list of types, I want the function instantiated and called for all permutations of the types in the list; the additional argument(s), x, just need to be forwarded the same for all instances.
Actually I got it working, see http://codepad.org/tnYTy9Iw.
I don't think that my solution is very good though. First, it has some run-time overhead due to the use of boost::bind in fwd1 and fwd2 (see link above.) Second, I'd like the macro that defines the type list not to be hard-coded in fwd1 and fwd2.
Is this possible?
How does this work
#include <boost/preprocessor/seq/for_each_product.hpp> #include <boost/preprocessor/seq/transform.hpp> #include <boost/preprocessor/seq/enum.hpp> #include <iostream>
struct func { typedef void result_type;
template <class A1,class A2,class A3> void operator()( A1, A2, A3, int x ) { std::cout << typeid(A1).name() << ',' << typeid(A2).name() << ',' << typeid(A3).name() << ',' << x << '\n';
} };
template<class T> T make() { return T(); }
#define CALL_FUNC(r, args) func()(BOOST_PP_SEQ_ENUM(args), x); #define MAKE_OBJECT(s, data, elem) make<elem>() #define FUNC_II(types) \ BOOST_PP_SEQ_FOR_EACH_PRODUCT(CALL_FUNC, (types)(types)(types)) #define FUNC_I(types) FUNC_II(types) #define FUNC(types, arg) \ if(true) { \ int x = arg; \ FUNC_I(BOOST_PP_SEQ_TRANSFORM(MAKE_OBJECT, ~, types)) \ } else ((void)0)
int main() { FUNC((int)(long), 42); }
In Christ, Steven Watanabe
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Sun, Aug 30, 2009 at 2:56 AM, Emil Dotchevski<emildotchevski@gmail.com> wrote:
Steven, thanks for your reply.
It is too late for me right now to understand your solution, but at first look it seems like it's very close to what I need but not quite. :)
The interface I need is something like:
CALL_PROD3(boost::bind(func(),_1,_2,_3,42),TYPE_LIST)
I do want to use bind (so I can pass any number of additional arguments to the function), and I don't want the function name or the type list macro name to be hard-coded. I just don't like the *nested* use of bind in the solution I posted, and the fact that the type list macro name is hard-coded in the helper functions fwd1 and fwd2.
It looks like for what you are doing then Boost.Phoenix and/or Boost.Fusion would do what you want without the prepocessor or tons of overloads.

On Sun, Aug 30, 2009 at 6:03 AM, OvermindDL1<overminddl1@gmail.com> wrote:
On Sun, Aug 30, 2009 at 2:56 AM, Emil Dotchevski<emildotchevski@gmail.com> wrote:
Steven, thanks for your reply.
It is too late for me right now to understand your solution, but at first look it seems like it's very close to what I need but not quite. :)
The interface I need is something like:
CALL_PROD3(boost::bind(func(),_1,_2,_3,42),TYPE_LIST)
I do want to use bind (so I can pass any number of additional arguments to the function), and I don't want the function name or the type list macro name to be hard-coded. I just don't like the *nested* use of bind in the solution I posted, and the fact that the type list macro name is hard-coded in the helper functions fwd1 and fwd2.
It looks like for what you are doing then Boost.Phoenix and/or Boost.Fusion would do what you want without the prepocessor or tons of overloads.
Can you give me a more specific starting point? Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

On Sun, Aug 30, 2009 at 12:31 PM, Emil Dotchevski<emildotchevski@gmail.com> wrote:
On Sun, Aug 30, 2009 at 6:03 AM, OvermindDL1<overminddl1@gmail.com> wrote:
On Sun, Aug 30, 2009 at 2:56 AM, Emil Dotchevski<emildotchevski@gmail.com> wrote:
Steven, thanks for your reply.
It is too late for me right now to understand your solution, but at first look it seems like it's very close to what I need but not quite. :)
The interface I need is something like:
CALL_PROD3(boost::bind(func(),_1,_2,_3,42),TYPE_LIST)
I do want to use bind (so I can pass any number of additional arguments to the function), and I don't want the function name or the type list macro name to be hard-coded. I just don't like the *nested* use of bind in the solution I posted, and the fact that the type list macro name is hard-coded in the helper functions fwd1 and fwd2.
It looks like for what you are doing then Boost.Phoenix and/or Boost.Fusion would do what you want without the prepocessor or tons of overloads.
Can you give me a more specific starting point?
From what I gather (might be wrong) it seems like you are trying to create bindings of multiple unknown types and handling things by binding, most of that can be handled by fusion's invoke and its kin functions. Boost.Function_Types actually has an interpreter example that uses fusion for about half of what you would need. I am really short on time at the moment and do not full understand your problem domain yet, but if you give a lot of pseudo-code about what you want done (not how you are currently trying to do it, but what you are trying to achieve), then I might try to whip up an example on Tuesday or so unless you or someone else beat me to it.

On Sun, Aug 30, 2009 at 2:39 PM, OvermindDL1<overminddl1@gmail.com> wrote:
From what I gather (might be wrong) it seems like you are trying to create bindings of multiple unknown types and handling things by binding
No, that is not what I'm trying to do. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
participants (4)
-
Emil Dotchevski
-
Emil Dotchevski
-
OvermindDL1
-
Steven Watanabe