Boost logo

Boost Users :

Subject: Re: [Boost-users] [preprocessor] removing parentheses
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2010-08-06 12:40:07


Edward Diener wrote:
> On 8/5/2010 1:50 PM, Steven Watanabe wrote:
>> The processor library doesn't support it, since the solution requires
>> variadic macros. The preprocessor output from the following seems
>> to be correct with msvc 2005 and gcc 4.4.1
>> #define CAT(x, y) CAT_I(x, y)
>> #define CAT_I(x, y) x ## y
>> #define APPLY(macro, args) APPLY_I(macro, args)
>> #define APPLY_I(macro, args) macro args
>> #define STRIP_PARENS(x) EVAL((STRIP_PARENS_I x), x)
>> #define STRIP_PARENS_I(...) 1,1
>> #define EVAL(test, x) EVAL_I(test, x)
>> #define EVAL_I(test, x) MAYBE_STRIP_PARENS(TEST_ARITY test, x)
>> #define TEST_ARITY(...) APPLY(TEST_ARITY_I, (__VA_ARGS__, 2, 1))
>> #define TEST_ARITY_I(a,b,c,...) c
>> #define MAYBE_STRIP_PARENS(cond, x) MAYBE_STRIP_PARENS_I(cond, x)
>> #define MAYBE_STRIP_PARENS_I(cond, x) CAT(MAYBE_STRIP_PARENS_, cond)(x)
>> #define MAYBE_STRIP_PARENS_1(x) x
>> #define MAYBE_STRIP_PARENS_2_I(...) __VA_ARGS__
>> STRIP_PARENS(this is a test)
>> STRIP_PARENS((a,b,c))
> I can not figure out how this code works. Evidently the rules for
> recursive macro invocation eludes me, no matter how many times I have
> read the 16.13.1 in the C++ working draft.

Alright. Here's stepping through the evaluation
of the two macro invocations. (I may have the evaluation
order slightly wrong, but it doesn't affect the final

STRIP_PARENS(this is a test)
EVAL((STRIP_PARENS_I this is a test), this is a test)
   At this point the first argument is either STRIP_PARENS_I
   followed by the original argument or it is 1,1. We can distinguish
   the two by checking the size as a tuple.
EVAL_I((STRIP_PARENS_I this is a test), this is a test)
   Now we expand TEST_ARITY which returns the number of elements in its
   argument. In this case, the result will be 1.
APPLY(TEST_ARITY_I, (STRIP_PARENS_I this is a test, 2, 1))
APPLY_I(TEST_ARITY_I, (STRIP_PARENS_I this is a test, 2, 1))
TEST_ARITY_I (STRIP_PARENS_I this is a test, 2, 1)
TEST_ARITY_I (STRIP_PARENS_I this is a test, 2, 1)
   Now we can go back to MAYBE_STRIP_PARENS.
   We're going to switch on the tuple size (which we just
   found)to decide whether we need to remove parentheses.
MAYBE_STRIP_PARENS(1, this is a test)
MAYBE_STRIP_PARENS_I(1, this is a test)
CAT(MAYBE_STRIP_PARENS_, 1)(this is a test)
MAYBE_STRIP_PARENS_1(this is a test)
this is a test.

   In the second case we get
EVAL((STRIP_PARENS_I (a,b,c)), (a,b,c))
   STRIP_PARENS_I can be expanded to get
EVAL((1,1), (a,b,c))
   Now we we check the arity, we end up with
TEST_ARITY_I (1,1, 2, 1)
   which expands to 2, and we select
   the expansion of which should be straightforward

In Christ,
Steven Watanabe

Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at