Boost logo

Boost Users :

Subject: Re: [Boost-users] [preprocessor] removing parentheses
From: Edward Diener (eldiener_at_[hidden])
Date: 2010-08-06 11:22:14


On 8/5/2010 1:50 PM, Steven Watanabe wrote:
> AMDG
>
> Edward Diener wrote:
>> 1) I do not know ( or normally care ) how many commas are in the
>> parenthesized value ( ie. size of the tuple )
>>
>> 2) The value can be passed without any parentheses and therefore not
>> be a tuple. For this second problem I can force the end-user always to
>> put parentheses around the passed value, even if it does not need it
>> to form a single macro value. But 1) would still remain a problem. Of
>> course I could solve 1) by forcing the end-user to also pass the
>> number of commas in the parenthesized value as a separate template
>> parameter, but I think that is too much of a burden for the end-user.
>>
>> I just want the end-user to pass the value as a single macro
>> parameter, and to use the value without the outer parentheses if the
>> value contains commas. But perhaps this is just impossible to do with
>> C++'s macro facilities. The preprocessing library is so great I was
>> hoping it could even solve this problem. In reality I may not need to
>> strip off the parentheses from the value ( which in my particular case
>> forms part of a C++ declaration ), since redundant parentheses almost
>> ( possibly ) never causes a syntax error in C++.
>>
>> It does seems as if the preprocessor library should have the
>> functionality I require since it is able to extract a value from a
>> sequence via BOOST_PP_SEQ_ELEM, and a sequence can be in the simple
>> form of '(value)'. However my tests show that if I pass a
>> non-sequence, such as just 'value' to BOOST_PP_SEQ_ELEM, the compiler
>> gives a warning and the result is bogus.
>
> 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(x) APPLY(MAYBE_STRIP_PARENS_2_I, 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.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net