Boost logo

Boost :

From: Arias Brent-P96059 (Brent.Arias_at_[hidden])
Date: 2004-11-19 12:06:43


>Not a bug. Empty macro arguments are currently undefined behavior in C++.
There is nothing that I can do about that. C99 added explicit support for them, but they are not (yet) part of C++.

I very much appreciate your answer. And ultimately this hasn't become a big deal, since - as you saw - I found a way around the problem all the same.

But now let me answer a very good question you asked:

> #define ENUM(name, start, entries)\
> BOOST_PP_SEQ_ENUM( \
> BOOST_PP_IIF(ENUMS, \
> (typedef enum{ BOOST_PP_SEQ_HEAD(entries) = start) \
> BOOST_PP_SEQ_TAIL(entries) \
> (LAST_##name } name;) \
> , \
> (static void PP_NILFUNC();) \
> ) \
> )

>Why are you doing the test *inside* of the invocation of SEQ_ENUM?

The short answer: I wanted a **single** ENUM macro definition that permitted the printable strings *AND* the enums themselves to be conditionally compileable.

I think my intention will make more sense if I show you the entire printable enum. It looks like this:

#ifndef ENUMS /*By default, turn enums on*/
#define ENUMS 1
#endif
#ifndef ESTRINGS /*By default, turn printable strings on*/
#define ESTRINGS 1
#endif
#ifndef EDEBUG
#define EDEBUG 0 /*By default, turn ESTRINGS "compliment" condition off */
#endif

/*Used internally by the ENUM macro*/
#ifdef ENUM_STR
#undef ENUM_STR
#endif
#define ENUM_STR(r, data, elem) BOOST_PP_STRINGIZE(elem)

#define ENUM(name, start, entries) \
BOOST_PP_SEQ_ENUM( \
   BOOST_PP_IIF(ENUMS, \
      (typedef enum{ BOOST_PP_SEQ_HEAD(entries) = start) \
      BOOST_PP_SEQ_TAIL(entries) \
      (LAST_##name } name;) \
      , \
      (static void PP_NILFUNC();) \
   ) \
) \
BOOST_PP_SEQ_ENUM( \
   BOOST_PP_IIF(BOOST_PP_BITOR(EDEBUG,ESTRINGS), \
      (static const char* name##_Str[]={ BOOST_PP_STRINGIZE(BOOST_PP_SEQ_HEAD(entries)) ) \
      BOOST_PP_SEQ_TRANSFORM(ENUM_STR, _, BOOST_PP_SEQ_TAIL(entries) ) \
      (};) \
      , \
      (static void PP_NILFUNC();) \
   ) \
)

Now, as I think you pointed out yourself, you can't place the BOOST_PP_SEQ_ENUM inside of a BOOST_PP_EXPR_IIF statement like this:

#define ENUM(name, start, entries) \
    BOOST_PP_EXPR_IIF(ENUMS)( \
        BOOST_PP_SEQ_ENUM( \
            (typedef enum { BOOST_PP_SEQ_HEAD(entries) = start) \
            BOOST_PP_SEQ_TAIL(entries) \
            (LAST_ ## name } name;) \
        ) \
    ) \

So, what I've shown you in the printable enum above was the only solution I could think of to achieve the result: i.e. a **single** ENUM macro definition that permitted the printable strings *AND* the enums themselves to be conditionally compileable.

On the other hand, I'm intrigued with what you presented here:

#define ENUM(name, start, entries) \
    BOOST_PP_IIF( \
        ENUMS, \
        BOOST_PP_SEQ_ENUM, BOOST_PP_TUPLE_EAT(1) \
    )( \
        (typedef enum { BOOST_PP_SEQ_HEAD(entries) = start) \
        BOOST_PP_SEQ_TAIL(entries) \
        (LAST_ ## name } name;) \
    ) \

I didn't pay attention to BOOST_PP_TUPLE_EAT when I was (frantically) trying to make a printable enum. Perhaps it is a means by which I can get rid of the "hack" I described earlier? It sure looks like it will work!

Oh, by the way, I was so pleased with the printable enum - I was actually thinking of submitting it for inclusion into Boost. Would a submission like that be more nuisance than benefit?

Thanks,

-Brent


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