[preprocessor] missing IS_EMPTY documentation?

Hello all, Is there a reason why `BOOST_PP_IS_EMPTY()` is not part of Boost.Preprocessor reference documentation? 1) I think this macro is part of the library public API because it is in <boost/preprocessor/facilities/is_empty.hpp> (outside the "detail/" directory and same location as `BOOST_PP_EMPTY` which is documented). 2) Is it OK to use `PP_IS_EMPTY()` to check if a macro expansion is actually empty or not? For example: #include <boost/preprocessor/facilities/empty.hpp> #include <boost/preprocessor/facilities/is_empty.hpp> #define X /* expand to nothing */ #define Y BOOST_PP_EMPTY #define Z a b c BOOST_PP_EMPTY BOOST_PP_IS_EMPTY(X) // expand to 1 BOOST_PP_IS_EMPTY(Y()) // expand to 1 BOOST_PP_IS_EMPTY(Y) // expand to 0 BOOST_PP_IS_EMPTY(Z()) // expand to 0 Thank you for the clarification. -- Lorenzo

-------- Original-Nachricht --------
Datum: Fri, 3 Sep 2010 11:29:41 -0400 Von: Lorenzo Caminiti <lorcaminiti@gmail.com> An: boost@lists.boost.org Betreff: [boost] [preprocessor] missing IS_EMPTY documentation?
Hello all,
Is there a reason why `BOOST_PP_IS_EMPTY()` is not part of Boost.Preprocessor reference documentation?
1) I think this macro is part of the library public API because it is in <boost/preprocessor/facilities/is_empty.hpp> (outside the "detail/" directory and same location as `BOOST_PP_EMPTY` which is documented).
I think it is not part of the API, because it does not conform to C90. You must not submit parameters to macros that expand to nothing, because C90 does not cover this situation
2) Is it OK to use `PP_IS_EMPTY()` to check if a macro expansion is actually empty or not? For example:
#include <boost/preprocessor/facilities/empty.hpp> #include <boost/preprocessor/facilities/is_empty.hpp>
#define X /* expand to nothing */ #define Y BOOST_PP_EMPTY #define Z a b c BOOST_PP_EMPTY
BOOST_PP_IS_EMPTY(X) // expand to 1 BOOST_PP_IS_EMPTY(Y()) // expand to 1 BOOST_PP_IS_EMPTY(Y) // expand to 0 BOOST_PP_IS_EMPTY(Z()) // expand to 0
Thank you for the clarification.
Even if you use a C99 compliant preprocessor, there are some pitfalls lurking around. It tests the emptyness of something that expands to an unsigned integer or an identifier only. Examples #define A foo #define B (foo) #define C 1 #define D BOOST_PP_IS_EMPTY(A) // ok BOOST_PP_IS_EMPTY(B) // error BOOST_PP_IS_EMPTY(C) // ok BOOST_PP_IS_EMPTY(D) // ok -- GMX DSL SOMMER-SPECIAL: Surf & Phone Flat 16.000 für nur 19,99 Euro/mtl.!* http://portal.gmx.net/de/go/dsl

On 9/3/2010 8:29 AM, Lorenzo Caminiti wrote:
Hello all,
Is there a reason why `BOOST_PP_IS_EMPTY()` is not part of Boost.Preprocessor reference documentation?
1) I think this macro is part of the library public API because it is in<boost/preprocessor/facilities/is_empty.hpp> (outside the "detail/" directory and same location as `BOOST_PP_EMPTY` which is documented).
2) Is it OK to use `PP_IS_EMPTY()` to check if a macro expansion is actually empty or not? For example:
#include<boost/preprocessor/facilities/empty.hpp> #include<boost/preprocessor/facilities/is_empty.hpp>
#define X /* expand to nothing */ #define Y BOOST_PP_EMPTY #define Z a b c BOOST_PP_EMPTY
BOOST_PP_IS_EMPTY(X) // expand to 1 BOOST_PP_IS_EMPTY(Y()) // expand to 1 BOOST_PP_IS_EMPTY(Y) // expand to 0 BOOST_PP_IS_EMPTY(Z()) // expand to 0
Thank you for the clarification.
I'm not sure why there are no docs for it, but it is part of the public API. There are three related macros, IS_EMPTY, IS_1, and IS_EMPTY_OR_1 that are all related to the detection of compilation flags which might be defined (possibly as nothing) via a command line or somewhere in the source. For example, #define A #define B 1 #define C 0 IS_EMPTY(A) => 1 IS_EMPTY(B) => 0 IS_EMPTY(C) => 0 IS_1(A) => 0 IS_1(B) => 1 IS_1(C) => 0 IS_EMPTY_OR_1(A) => 1 IS_EMPTY_OR_1(B) => 1 IS_EMPTY_OR_1(C) => 0 However, IS_EMPTY is _not_ a macro for general-purpose emptiness detection. Its implementation requires the concatenation of an identifier to the front of the argument which rules out all arguments for which that isn't valid. For example, IS_EMPTY(+) is undefined behavior according to all revisions of both the C and C++ standards (including the forthcoming C++0x). Thus, at minimum, the argument must be an identifier (or keyword--same thing at this point) or a numeric literal that doesn't contain a decimal point. What Wolf said in his reply is wrong or, at least, partially wrong. It is valid (and has been since C90) to pass something that expands to nothing as an argument to a macro. However, it is not valid to pass nothing. E.g. #define BLANK #define A(x) x A(BLANK) // valid, even in C90 and C++98 A() // invalid in C90/C++98 // but valid in C99/C++0x #define B(x) A(x) B(BLANK) // invalid in C90/C++98 // but valid in C99/C++0x AFAIK, there is absolutely no way to create a general-purpose emptiness-detection macro even in C99 or C++0x and even if you exclude pathological input such as: #define LPAREN ( MACRO( LPAREN ) // pathological You can, however, get close in several ways, but the input is always restricted. E.g. the above requires input that expands to nothing, an identifier, or a number (without a '.') (or, more accurately, the result of expansion _starts_ with such a token). Another method gets you everything but pathological input and input that expands to something that ends with a function-like macro name without the parentheses and arguments (if any). And that is the best you can do in this area. Regards, Paul Mensonides

I wrote wrt to BOOST_PP_IS_EMPTY: "I think it is not part of the API, because it does not conform to C90. You must not submit parameters to macros that expand to nothing, because C90 does not cover this situation" The relevant portions of the standard makes it clear: "If (before argument substitution) any argument consists of no preprocessing tokens, the behavior is undefined." ... "After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place" ... "Before being substituted, each argument's preprocessing tokens are completely macro replaced as if they formed the rest of the source file" Paul Mensonides is right, an argument must not be empty, when it is collected, but it may be at the moment when it is substituted for a parameter. I was mislead by the double mention and meaning of "substitute/substitution", but argument substitution (as opposed to parameter substitution) is the combined process of expanding the argument and substitution for a parameter, and checking for emptyness takes place prior to "argument substitution". I apologize for having given a wrong interpretation and hope this have not lead to too much confusion. Regards Wolf Lammen -- GMX DSL SOMMER-SPECIAL: Surf & Phone Flat 16.000 für nur 19,99 Euro/mtl.!* http://portal.gmx.net/de/go/dsl

On 9/6/2010 3:17 PM, Wolf Lammen wrote:
I wrote wrt to BOOST_PP_IS_EMPTY:
"I think it is not part of the API, because it does not conform to C90. You must not submit parameters to macros that expand to nothing, because C90 does not cover this situation"
The relevant portions of the standard makes it clear:
"If (before argument substitution) any argument consists of no preprocessing tokens, the behavior is undefined." ... "After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place" ... "Before being substituted, each argument's preprocessing tokens are completely macro replaced as if they formed the rest of the source file"
Paul Mensonides is right, an argument must not be empty, when it is collected, but it may be at the moment when it is substituted for a parameter. I was mislead by the double mention and meaning of "substitute/substitution", but argument substitution (as opposed to parameter substitution) is the combined process of expanding the argument and substitution for a parameter, and checking for emptyness takes place prior to "argument substitution".
I apologize for having given a wrong interpretation and hope this have not lead to too much confusion.
Luckily, it no longer matters in C and will no longer matter in C++ shortly. Regards, Paul Mensonides

On Mon, Sep 6, 2010 at 7:30 PM, Paul Mensonides <pmenso57@comcast.net> wrote:
On 9/6/2010 3:17 PM, Wolf Lammen wrote:
I wrote wrt to BOOST_PP_IS_EMPTY:
"I think it is not part of the API, because it does not conform to C90. You must not submit parameters to macros that expand to nothing, because C90 does not cover this situation"
The relevant portions of the standard makes it clear:
"If (before argument substitution) any argument consists of no preprocessing tokens, the behavior is undefined." ... "After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place" ... "Before being substituted, each argument's preprocessing tokens are completely macro replaced as if they formed the rest of the source file"
Paul Mensonides is right, an argument must not be empty, when it is collected, but it may be at the moment when it is substituted for a parameter. I was mislead by the double mention and meaning of "substitute/substitution", but argument substitution (as opposed to parameter substitution) is the combined process of expanding the argument and substitution for a parameter, and checking for emptyness takes place prior to "argument substitution".
I apologize for having given a wrong interpretation and hope this have not lead to too much confusion.
Luckily, it no longer matters in C and will no longer matter in C++ shortly.
Thanks a lot to all for the replies and clarifications. I think I understand the situation. I use IS_EMPTY more or less like this: #define HAS_NO_OPTION(x) BOOST_PP_IS_EMPTY(x) #define NO_OPTION BOOST_PP_EMPTY #define XYZ_OPTION xyz BOOST_PP_EMPTY HAS_NO_OPTION(NO_OPTION()) // expand to 1 HAS_NO_OPTION(XYZ_OPTION()) // expand to 0 This seems fine because I never pass an empty macro parameter (but only parameters that eventually expand to empty, which is fine). Plus, by construction, `x` only contains literals or numbers with no dot. (MORE BACKGROUND: This is an implementation detail of my parenthesized syntax pp-parsers. For example, a member function might or no be `const`, so after parsing `const` is represented internally as either `BOOST_PP_EMPTY` or `const BOOST_PP_EMPTY` within an array of parsed function signature traits called `sign`. Then trait inspection macros can be applied to check `IS_CONST(sign)`. These inspection macros expand `BOOST_PP_EMPTY` and check for emptiness using `BOOST_PP_IS_EMPTY()`. This implementation works on both GCC and MSVC.) -- Lorenzo
participants (3)
-
Lorenzo Caminiti
-
Paul Mensonides
-
Wolf Lammen