Boost logo

Boost :

Subject: Re: [boost] [preprocessor] missing IS_EMPTY documentation?
From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2010-09-06 15:29:19


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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk