_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Except that:
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.
Have you considered using a variadic macro? I hear they're not
available for all C++ precompilers, but it may do what you want:
Instead of
#define YOUR_MACRO( NOCOMMASALLOWED ) NOCOMMASALLOWED
you might use
#define YOUR_MACRO( ... ) __VA_ARGS__
I know it's only "one" argument you're after, but this would at least
pull the commas through in-tact.
Variadic macros would indeed be a solution if the compiler(s) I am using
supported that feature. But I am really trying to do work for inclusion
into Boost itself and very few compilers support variadic macros as yet.
Edward Diener wrote:
> Variadic macros would indeed be a solution if the compiler(s) I am
> using supported that feature. But I am really trying to do work for
> inclusion into Boost itself and very few compilers support variadic
> macros as yet.
MSVC and gcc have both supported variadic macros for a while.
In Christ,
Steven Watanabe
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))
In Christ,
Steven Watanabe
Regarding MSVC, I have really been asleep regarding variadic macros.
Thanks for awakening me.
What is the boost configuration macro for this feature ? I searched for
'variadic' in the config macro page but did not find anything for
variadic macros.
Correct me if I'm wrong (wouldn't surprise me), but aren't variadic
macros technically a C99 thing, and from a C++ perspective always an
extension to the language?
If that's the case, and he's developing something he wants to share
with users of many different platforms and compilers, I completely
understand why it's not a very good solution.
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
result.)
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)
MAYBE_STRIP_PARENS(TEST_ARITY (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)
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
MAYBE_STRIP_PARENS_2((a,b,c))
the expansion of which should be straightforward
In Christ,
Steven Watanabe
Many thanks !