
I am not terribly familiar with the rules of the preprocessor. Is it the case that the expression of the BOOST_PP_EXPR_IF macro is expanded regardless of the resulting value of the condition? The reason I ask is because the following code produces a warning with VC7 .NET 2003. #define MY_MACRO(array) \ BOOST_PP_EXPR_IF( \ BOOST_PP_ARRAY_SIZE(array), \ BOOST_PP_TUPLE_TO_SEQ( \ BOOST_PP_ARRAY_SIZE(array), \ BOOST_PP_ARRAY_DATA(array) \ ) \ ) MY_MACRO((0, ())); The warning is: C4003: not enough actual parameters for macro 'BOOST_PP_EXPR_IIF_0' The macro expands correctly. Perhaps there is a better way to do what I am after. I would like to create a comma separated list (no parenthesis as would be the case if I only took the array data) from a possibly empty set. Thanks, John

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of John Eddy Sent: Wednesday, February 02, 2005 12:35 PM To: boost@lists.boost.org Subject: [boost] BOOST_PP_EXPR_IF Behavior
I am not terribly familiar with the rules of the preprocessor. Is it the case that the expression of the BOOST_PP_EXPR_IF macro is expanded regardless of the resulting value of the condition?
For EXPR_IF, yes. If and only if an argument to a macro appears in the replacement list of that macro without being an operand of # or ##, then that argument should be expanded on input to the macro--regardless of whether the argument is relevant to the final result of macro expansion. Note the "and only if" part above in particular. Minus all the workarounds, EXPR_IF is defined like this: #define EXPR_IF(cond, expr) EXPR_IIF(BOOL(cond), expr) I.e. it simply defers to EXPR_IIF after converting the condition to 0 or 1. Note that 'expr' appears in the replacement list without being an operand of # or ##. EXPR_IIF is the same way, but defined differently: #define EXPR_IIF(bit, expr) CAT(EXPR_IIF_, bit)(expr) #define EXPR_IIF_0(expr) #define EXPR_IIF_1(expr) expr In other words, in both cases, 'expr' will be expanded regardless of 'cond' or 'bit'. With that said, EXPR_IF (etc.) is only defined that the way it is because preprocessors are non-conformant. If I could encapsulate their problems (which I can't), I would do it this way: #define EXPR_IF(cond) CAT(EXPR_IF_, BOOL(cond)) #define EXPR_IF_0(expr) #define EXPR_IF_1(expr) expr The usage syntax would then be: EXPR_IF ( condition ) ( expression ) instead of EXPR_IF ( condition , expression ) The difference is that the former is lazy. If 'cond' is 0, 'expr' is passed to a macro that does not mention 'expr' in its replacement list and thus should not be expanded. Unfortunately, I cannot effectively encapsulate preprocessor bugs with this kind of "combination" syntax. [As an aside, to those who may be interested: with placemarkers (i.e. empty arguments) from C99, macros can propogate "lack of evaluation" by placemarker concatenation--which does not change the tokens in the argument but does prevent them from expanding on input.]
The warning is:
C4003: not enough actual parameters for macro 'BOOST_PP_EXPR_IIF_0'
The macro expands correctly.
Don't rely on that. It's a VC misfeature; it should be an error.
Perhaps there is a better way to do what I am after. I would like to create a comma separated list (no parenthesis as would be the case if I only took the array data) from a possibly empty set.
Okay, let me see if I understand correctly. You have an array (as in the pp data structure) which looks like (e.g.): (0, ()) (1, (a)) (2, (a, b)) (3, (a, b, c)) // etc. And you want this transformation: (0, ()) -> (1, (a)) -> a (2, (a, b)) -> a, b (3, (a, b, c)) -> a, b, c Assuming that that is what you want... #include <boost/preprocessor/array/data.hpp> #include <boost/preprocessor/array/size.hpp> #include <boost/preprocessor/tuple/rem.hpp> #define ARRAY_ENUM(array) \ BOOST_PP_TUPLE_REM_CTOR( \ BOOST_PP_ARRAY_SIZE(array), \ BOOST_PP_ARRAY_DATA(array) \ ) \ /**/ ARRAY_ENUM( (0, ()) ) // -> ARRAY_ENUM( (1, (a)) ) // -> a ARRAY_ENUM( (2, (a, b)) ) // -> a, b ARRAY_ENUM( (3, (a, b, c)) ) // -> a, b, c Regards, Paul Mensonides

Many thanks. That worked perfectly. I did not catch the acceptance of 0 sized tupes in BOOST_PP_TUPLE_REM_CTOR. Thanks, John Paul Mensonides wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of John Eddy Sent: Wednesday, February 02, 2005 12:35 PM To: boost@lists.boost.org Subject: [boost] BOOST_PP_EXPR_IF Behavior
I am not terribly familiar with the rules of the preprocessor. Is it the case that the expression of the BOOST_PP_EXPR_IF macro is expanded regardless of the resulting value of the condition?
For EXPR_IF, yes. If and only if an argument to a macro appears in the replacement list of that macro without being an operand of # or ##, then that argument should be expanded on input to the macro--regardless of whether the argument is relevant to the final result of macro expansion. Note the "and only if" part above in particular. Minus all the workarounds, EXPR_IF is defined like this:
#define EXPR_IF(cond, expr) EXPR_IIF(BOOL(cond), expr)
I.e. it simply defers to EXPR_IIF after converting the condition to 0 or 1. Note that 'expr' appears in the replacement list without being an operand of # or ##. EXPR_IIF is the same way, but defined differently:
#define EXPR_IIF(bit, expr) CAT(EXPR_IIF_, bit)(expr) #define EXPR_IIF_0(expr) #define EXPR_IIF_1(expr) expr
In other words, in both cases, 'expr' will be expanded regardless of 'cond' or 'bit'.
With that said, EXPR_IF (etc.) is only defined that the way it is because preprocessors are non-conformant. If I could encapsulate their problems (which I can't), I would do it this way:
#define EXPR_IF(cond) CAT(EXPR_IF_, BOOL(cond)) #define EXPR_IF_0(expr) #define EXPR_IF_1(expr) expr
The usage syntax would then be:
EXPR_IF ( condition ) ( expression )
instead of
EXPR_IF ( condition , expression )
The difference is that the former is lazy. If 'cond' is 0, 'expr' is passed to a macro that does not mention 'expr' in its replacement list and thus should not be expanded. Unfortunately, I cannot effectively encapsulate preprocessor bugs with this kind of "combination" syntax.
[As an aside, to those who may be interested: with placemarkers (i.e. empty arguments) from C99, macros can propogate "lack of evaluation" by placemarker concatenation--which does not change the tokens in the argument but does prevent them from expanding on input.]
The warning is:
C4003: not enough actual parameters for macro 'BOOST_PP_EXPR_IIF_0'
The macro expands correctly.
Don't rely on that. It's a VC misfeature; it should be an error.
Perhaps there is a better way to do what I am after. I would like to create a comma separated list (no parenthesis as would be the case if I only took the array data) from a possibly empty set.
Okay, let me see if I understand correctly. You have an array (as in the pp data structure) which looks like (e.g.):
(0, ()) (1, (a)) (2, (a, b)) (3, (a, b, c)) // etc.
And you want this transformation:
(0, ()) -> (1, (a)) -> a (2, (a, b)) -> a, b (3, (a, b, c)) -> a, b, c
Assuming that that is what you want...
#include <boost/preprocessor/array/data.hpp> #include <boost/preprocessor/array/size.hpp> #include <boost/preprocessor/tuple/rem.hpp>
#define ARRAY_ENUM(array) \ BOOST_PP_TUPLE_REM_CTOR( \ BOOST_PP_ARRAY_SIZE(array), \ BOOST_PP_ARRAY_DATA(array) \ ) \ /**/
ARRAY_ENUM( (0, ()) ) // -> ARRAY_ENUM( (1, (a)) ) // -> a ARRAY_ENUM( (2, (a, b)) ) // -> a, b ARRAY_ENUM( (3, (a, b, c)) ) // -> a, b, c
Regards, Paul Mensonides
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (2)
-
John Eddy
-
Paul Mensonides