$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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