|
Boost : |
From: Stjepan Rajko (stipe_at_[hidden])
Date: 2007-05-31 12:02:41
Sorry, never mind :-) - Tobias pointed me to fusion and
function_types::parameter_types, which looks like a much better way to
do what I'm trying to accomplish anyway (and he also pointed out a
nicer way to do the macro expansion I was proposing using what's
already in PP)
Apologies for the noise!
Stjepan
On 5/30/07, Stjepan Rajko <stipe_at_[hidden]> wrote:
> Hello,
>
> I would like to propose an extension to the Preprocessor library,
> based on the REPEAT, ENUM etc. family of macros, e.g.,
> BOOST_PP_REPEAT(count, macro, data) macro which expands to:
>
> macro(z, 0, data) macro(z, 1, data) ... macro(z, count - 1, data)
>
> In working on the RPC and Signal Network libraries, I found useful
> being able to iterate over multiple macros simultaneously. This could
> be provided by a set of macros BOOST_PP_REPEAT_(C|M|MA)+ where C
> stands for Constant, M for Macro, and MA for Macro+Argument. For
> example,
>
> BOOST_PP_REPEAT_CMAMC(count, cons, macro, arg, macro2, cons2) expands
> to (linebreaks inserted for readability):
>
> cons macro(z, 0, arg) macro2(z, 0, BOOST_PP_EMPTY()) cons2
> cons macro(z, 1, arg) macro2(z, 1, BOOST_PP_EMPTY()) cons2
> ...
> cons macro(z, count-1, arg) macro2(z, count-1, BOOST_PP_EMPTY()) cons2
>
> This particular macro would be implemented as
>
> #define BOOST_PP_CMAMC_MACRO(z, n, args) \
> BOOST_PP_TUPLE_ELEM(5, 0, args) \
> BOOST_PP_TUPLE_ELEM(5, 1, args)(z,n,BOOST_PP_TUPLE_ELEM(5, 2, args)) \
> BOOST_PP_TUPLE_ELEM(5, 3, args)(z,n,BOOST_PP_EMPTY()) \
> BOOST_PP_TUPLE_ELEM(5, 4, args)
>
> #define BOOST_PP_REPEAT_CMAMC(count, c1, m2, a3, m4, c5) \
> BOOST_PP_REPEAT(count, BOOST_PP_CMAMC_MACRO, (c1, m2, a3, m4, c5))
>
> As a usage example, I am finding such expansions useful in developing
> classes / functions in which an integer template parameter determines
> the number of arguments to a function/method and/or the number of
> local/class variables (for example, when the function signature is
> determined by a signature provided as a template parameter, and the
> function needs a local variable for each parameter). In this case, I
> iterate over the a template implementation using BOOST_PP_ITERATE and
> have a set of macros equivalent to the ones above, except they
> hard-code the count to BOOST_PP_ITERATION() (they are called
> BOOST_ARITY_* instead of BOOST_PP_*).
>
> Take as an example a function "serialize" which is templated on a
> function Signature, where the arguments of the function are specified
> by the signature. For example,
>
> std::string serialized_params;
> serialized_params = serialize<void(int, float, std::string)>(1, 2.5,
> "serialize this");
>
> The above macros make the following implementation a little more
> readable than other alternatives I've come accross (what follows is
> adapted from working code and untested):
>
> --- first some prep work, so we have macros to iterate over:
>
> // define names a1, a2, ...
> #define ARITY_aN_NAME(z,n,data) \
> BOOST_PP_CAT(a,BOOST_PP_INC(n))
>
> // define names arg1_type, arg2_type, ...:
> #define ARITY_argN_type_NAME(z,n,data) \
> BOOST_PP_CAT(BOOST_PP_CAT(arg,BOOST_PP_INC(n)),_type)
>
> // define a way to get to the type of an argument, given the signature:
> #define ARITY_function_traits_argN_type_NAME(z,n,signature) \
> typename boost::function_traits<signature>:: \
> ARITY_argN_type_NAME(z,n,BOOST_PP_EMPTY())
>
> // just some shortcuts:
> #define BOOST_ARITY_ENUM_MAM(m1, a2, m3) \
> BOOST_PP_ENUM_MAM(BOOST_PP_ITERATION(), m1, m2, m3)
>
> #define BOOST_ARITY_REPEAT_CMC(c1, m2, c3) \
> BOOST_PP_REPEAT_CMC(BOOST_PP_ITERATION(), c1, m2, c3)
>
> ---- the following part is iterated over using BOOST_PP_ITERATE:
>
> // define a function which serializes its arguments, and the
> // number and type of arguments is specified by a template param:
>
> template<typename Signature>
>
> // retuns a string
> typename boost::enable_if_c<boost::function_traits<Signature>::arity
> ==BOOST_PP_ITERATION(), std::string>::type
>
> // the list of arguments is expanded through the macros:
> // (typename boost::function_traits<Signature>::arg1_type a1,
> // typename boost::function_traits<Signature>::arg2_type a2, ...)
> serialize(BOOST_ARITY_ENUM_MAM(ARITY_function_traits_argN_type_NAME,
> Signature, ARITY_aN_NAME))
> {
> std::stringstream stream(std::ios::in | std::ios::out | std::ios::binary);
> boost::archive::binary_oarchive archive(stream);
>
> // archive & a1; archive & a2; ...
> BOOST_ARITY_REPEAT_CMC(archive &, ARITY_aN_NAME, ;)
> return stream.str();
> }
>
> ---
>
> The BOOST_ARITY_* macros above are easily implemented using BOOST_PP_*
> macros, and are just one usage example. Macros of the type
> BOOST_PP_REPEAT_(C|M|MA)+ could probably have other applications as
> well.
>
> If there isn't functionality which already covers this, would there be
> any interest in adding the BOOST_PP_REPEAT_(C|M|MA)+ etc. macros to
> the preprocessor library? If so, I could write up a python script
> which would generate the macros for up to a reasonable number of
> arguments (e.g., four C, M, or MAs which would lead to 3^4 base macros
> plus the same number of BOOST_PP_REPEAT_*, BOOST_PP_EVAL_*, and any
> other macros that should be included).
>
> Regards,
>
> Stjepan
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk