|
Boost : |
Subject: Re: [boost] [Preprocessor] Adding variadic macros support
From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2010-11-29 08:33:23
On Wed, 24 Nov 2010 14:45:02 -0800, Jeffrey Lee Hellrung, Jr. wrote:
> On 11/24/2010 2:14 PM, Edward Diener wrote: [...]
>> I am still not sure what you mean by "macro composition" and "argument
>> binding" in a preprocessor library. Boost PP has much support for macro
>> composition within the context of what it offers in the form of
>> repeatable constructs, data types, etc. but I have a feeling you mean
>> something else. As far as "argument binding", in terms of preprocessor
>> macros all arguments are initially in the form of tokens, so I am not
>> sure what you mean by the phrase.
>
> Imagine Boost.MPL without placeholders.
>
> As a simple example, suppose you already have a macro handy:
>
> #define macro( n ) ...insert your favorite expression involving n...
>
> and want to use it in an invocation of BOOST_PP_ENUM. This requires
> defining a forwarding macro:
>
> #define macro2( z, n, data ) macro( n ) BOOST_PP_ENUM( N, macro2, ~ )
>
> Argument binding refers to the ability to bind the arguments of
> function-style macros to tokens or placeholders for tokens to be
> substituted later. So one would be able to do something like (making up
> the syntax from what I can remember)
>
> BOOST_PP_ENUM( N, BIND( macro, 2 ), ~ )
For what it's worth, with the way that Chaos invokes user-supplied
macros, it isn't difficult to provide general-purpose argument mappers.
The general form would be something like (for only three arguments)...
#define MAP(...) CHAOS_PP_VARIADIC_CAT(MAP_, __VA_ARGS__)
#define UNARY_MAP(n, ...) \
( \
CHAOS_PP_VARIADIC_ELEM(n, __VA_ARGS__) \
) \
/**/
#define MAP_0(...) UNARY_MAP(0, __VA_ARGS__)
#define MAP_1(...) UNARY_MAP(1, __VA_ARGS__)
#define MAP_2(...) UNARY_MAP(2, __VA_ARGS__)
#define BINARY_MAP(n, m, ...) \
( \
CHAOS_PP_VARIADIC_ELEM(n, __VA_ARGS__), \
CHAOS_PP_VARIADIC_ELEM(m, __VA_ARGS__) \
) \
/**/
#define MAP_01(...) BINARY_MAP(0, 1, __VA_ARGS__)
#define MAP_02(...) BINARY_MAP(0, 2, __VA_ARGS__)
#define MAP_10(...) BINARY_MAP(1, 0, __VA_ARGS__)
#define MAP_12(...) BINARY_MAP(1, 2, __VA_ARGS__)
#define MAP_20(...) BINARY_MAP(2, 0, __VA_ARGS__)
#define MAP_21(...) BINARY_MAP(2, 1, __VA_ARGS__)
#define TERNARY_MAP(n, m, o, ...) \
( \
CHAOS_PP_VARIADIC_ELEM(n, __VA_ARGS__), \
CHAOS_PP_VARIADIC_ELEM(m, __VA_ARGS__), \
CHAOS_PP_VARIADIC_ELEM(o, __VA_ARGS__) \
) \
/**/
#define MAP_012(...) TERNARY_MAP(0, 1, 2, __VA_ARGS__)
#define MAP_021(...) TERNARY_MAP(0, 2, 1, __VA_ARGS__)
#define MAP_102(...) TERNARY_MAP(1, 0, 2, __VA_ARGS__)
#define MAP_120(...) TERNARY_MAP(1, 2, 0, __VA_ARGS__)
#define MAP_201(...) TERNARY_MAP(2, 0, 1, __VA_ARGS__)
#define MAP_210(...) TERNARY_MAP(2, 1, 0, __VA_ARGS__)
#define A(n) n
CHAOS_PP_EXPR(CHAOS_PP_ENUM(
10, A MAP(1)
))
#define B(c, n) n / c
CHAOS_PP_EXPR(CHAOS_PP_ENUM(
10, B MAP(2, 1), 2
))
This, of course, is a combinatorial implementation, but for relatively
low numbers of arguments, it isn't too bad.
Regards,
Paul Mensonides
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk