Boost logo

Boost :

From: Vesa Karvonen (vesa_karvonen_at_[hidden])
Date: 2003-01-05 11:25:35


Hi,

A typical use of the C preprocessor is to use object-like macros as flags
for controlling code expansion:

  #if defined(OBJECT_LIKE_MACRO)
    EXPANDED_IF_DEFINED
  #else
    EXPANDED_IF_NOT_DEFINED
  #endif

The OBJECT_LIKE_MACRO is usually defined either in some configuration
header, or it may be defined on the command line. Most definitions are
either empty:

  #define OBJECT_LIKE_MACRO

or expand to 1:

  #define OBJECT_LIKE_MACRO 1

The above technique has a couple of problems. First of all, it can be
difficult to read, because preprocessor directives look very different from
ordinary C/C++ code. Furthermore, similar, but not exactly same, conditional
blocks (the above example is simplistic) may need to be used in several
places and it is quite tedious and verbose to make and use a parameterized
usable conditional block using the above base technique.

Preprocessor macros make parameterization and use easier. Unfortunately
there is no direct way to test, in a macro, whether some arbitrary macro is
defined. Usually the following tedious and verbose technique is used
instead:

  #if defined(OBJECT_LIKE_MACRO)
  # define OBJECT_LIKE_MACRO_BOOL 1
  #else
  # define OBJECT_LIKE_MACRO_BOOL 0
  #endif

  // ...

  BOOST_PP_IF(OBJECT_LIKE_MACRO_BOOL,
              EXPANDED_IF_DEFINED,
              EXPANDED_IF_NOT_DEFINED)

Ideally, we would have a predicate "is_defined(NAME)" that could be used in
a macro:

  BOOST_PP_IF(is_defined(OBJECT_LIKE_MACRO),
              EXPANDED_IF_DEFINED,
              EXPANDED_IF_NOT_DEFINED)

Unfortunately, it seems impossible to implement is_defined() using only
macros in the general case. In particular, consider the following macro
definition:

  #define X X

Fortunately we do not necessarily need a complete is_defined() predicate. In
most cases we only have to detect if a NAME becomes empty or the token 1
when expanded. It seems possible to say the following:

  BOOST_PP_IF(BOOST_PP_IS_EMPTY_OR_1(OBJECT_LIKE_MACRO),
              EXPANDED_IF_DEFINED,
              EXPANDED_IF_NOT_DEFINED)

I'd like to propose adding suitable predicate macros, in particular
BOOST_PP_IS_EMPTY(X), BOOST_PP_IS_1(X), BOOST_PP_IS_EMPTY_OR_1(X), to the
Boost Preprocessor library to help detect whether flag like macros are
defined. These macros would make it easier to move some logic from unusable
#if blocks into usable macros.

Best regards,
  Vesa Karvonen

...

// The following has been tested only on GNU cpp.

#include "boost/preprocessor/cat.hpp"
#include "boost/preprocessor/control/iif.hpp"
#include "boost/preprocessor/logical/bitor.hpp"
#include "boost/preprocessor/tuple/elem.hpp"

// `x' shall either expand to become empty or expand to a part of
// identifier or numeric literal token.
#define BOOST_PP_IS_EMPTY(x)\
  BOOST_PP_IS_EMPTY_DO(x BOOST_PP_IS_EMPTY_HELPER)
#define BOOST_PP_IS_EMPTY_DO(tuple_contents)\
  BOOST_PP_TUPLE_ELEM(2,1,(BOOST_PP_##tuple_contents))
#define BOOST_PP_BOOST_PP_IS_EMPTY_HELPER 1, 1
#define BOOST_PP_IS_EMPTY_HELPER , 0

// `x' shall expand to a part of identifier or numeric literal token.
#define BOOST_PP_IS_1(x)\
  BOOST_PP_IS_EMPTY(BOOST_PP_CAT(BOOST_PP_IS_1_HELPER_,x))
#define BOOST_PP_IS_1_HELPER_1

// `x' shall either expand to become empty or expand to a part of
// identifier or numeric literal token.
#define BOOST_PP_IS_EMPTY_OR_1(x)\
  BOOST_PP_IIF(BOOST_PP_IS_EMPTY_DO(x BOOST_PP_IS_EMPTY_HELPER),\
               1 BOOST_PP_EMPTY,\
               BOOST_PP_IS_1)(x)

// The following is test code

#include "boost/preprocessor/facilities/empty.hpp"

#define EMPTY

0 : BOOST_PP_IS_EMPTY(__cplusplus)
1 : BOOST_PP_IS_1(__cplusplus)
0 : BOOST_PP_IS_EMPTY(NOT_EMPTY)
0 : BOOST_PP_IS_1(NOT_EMPTY)
1 : BOOST_PP_IS_EMPTY(EMPTY)
0 : BOOST_PP_IS_EMPTY(whatever)
1 : BOOST_PP_IS_EMPTY(BOOST_PP_EMPTY())

1 : BOOST_PP_IS_EMPTY_OR_1(BOOST_PP_EMPTY())
1 : BOOST_PP_IS_EMPTY_OR_1(1)
0 : BOOST_PP_IS_EMPTY_OR_1(A)

_________________________________________________________________
Add photos to your e-mail with MSN 8. Get 2 months FREE*.
http://join.msn.com/?page=features/featuredemail


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