[preprocessor] removing parentheses

I have a single macro parameter which allows its passed value to contain commas. Therefore the user of the macro needs parentheses around the parameter if it contains one or more commas ( to does not have to ). When processing this parameter in a macro I would like to remove the outer parentheses if they are there before passing the value on for further processing. Is there a way to do this using some preprocessor library macro ?

I'm not sure without seeing exactly what you are trying to do, but perhaps http://www.boost.org/doc/libs/1_43_0/libs/preprocessor/doc/ref/tuple_rem.htm... or http://www.boost.org/doc/libs/1_43_0/libs/preprocessor/doc/ref/tuple_rem_cto... Could help you.
To: boost-users@lists.boost.org From: eldiener@tropicsoft.com Date: Wed, 4 Aug 2010 16:05:57 -0400 Subject: [Boost-users] [preprocessor] removing parentheses
I have a single macro parameter which allows its passed value to contain commas. Therefore the user of the macro needs parentheses around the parameter if it contains one or more commas ( to does not have to ). When processing this parameter in a macro I would like to remove the outer parentheses if they are there before passing the value on for further processing. Is there a way to do this using some preprocessor library macro ?
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On 8/4/2010 5:09 PM, Daniel Bradburn wrote:
I'm not sure without seeing exactly what you are trying to do, but perhaps
http://www.boost.org/doc/libs/1_43_0/libs/preprocessor/doc/ref/tuple_rem.htm...
or
http://www.boost.org/doc/libs/1_43_0/libs/preprocessor/doc/ref/tuple_rem_cto...
Could help you.
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.
To: boost-users@lists.boost.org From: eldiener@tropicsoft.com Date: Wed, 4 Aug 2010 16:05:57 -0400 Subject: [Boost-users] [preprocessor] removing parentheses
I have a single macro parameter which allows its passed value to contain commas. Therefore the user of the macro needs parentheses around the parameter if it contains one or more commas ( to does not have to ). When processing this parameter in a macro I would like to remove the outer parentheses if they are there before passing the value on for further processing. Is there a way to do this using some preprocessor library macro ?
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

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)) In Christ, Steven Watanabe

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.

AMDG 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(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.
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

On 8/6/2010 12:40 PM, Steven Watanabe wrote:
AMDG
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(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.
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
Many thanks !

On Wed, Aug 4, 2010 at 4:05 PM, Edward Diener
I have a single macro parameter which allows its passed value to contain commas. Therefore the user of the macro needs parentheses around the parameter if it contains one or more commas ( to does not have to ). When processing this parameter in a macro I would like to remove the outer parentheses if they are there before passing the value on for further processing. Is there a way to do this using some preprocessor library macro ?
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.

On 8/4/2010 7:07 PM, John B. Turpish wrote:
On Wed, Aug 4, 2010 at 4:05 PM, Edward Diener
wrote: I have a single macro parameter which allows its passed value to contain commas. Therefore the user of the macro needs parentheses around the parameter if it contains one or more commas ( to does not have to ). When processing this parameter in a macro I would like to remove the outer parentheses if they are there before passing the value on for further processing. Is there a way to do this using some preprocessor library macro ?
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.

AMDG 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

On 8/5/2010 1:47 PM, Steven Watanabe wrote:
AMDG
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.
Regarding MSVC, I have really been asleep regarding variadic macros. Thanks for awakening me.

On 8/5/2010 1:47 PM, Steven Watanabe wrote:
AMDG
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.
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.

On Thu, Aug 5, 2010 at 1:47 PM, Steven Watanabe
MSVC and gcc have both supported variadic macros for a while.
In Christ, Steven Watanabe
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.
participants (4)
-
Daniel Bradburn
-
Edward Diener
-
John B. Turpish
-
Steven Watanabe