Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2004-11-21 03:07:28

> -----Original Message-----
> From: boost-bounces_at_[hidden]
> [mailto:boost-bounces_at_[hidden]] On Behalf Of Arias Brent-P96059

> 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)\
> > (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:

I understand you're reasoning. The point I was making is, though preprocessor
metaprogramming is very different from programming in most languages, there are
still basic notions of computation, etc., such as control flow--which is nothing
but a conditional "invocation" of its accompanying code. Those kinds of things
still apply at the preprocessor level. What you really needed was a way to
conditionally enumerate some sequence elements, not enumerate a conditional

> 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) \
> (typedef enum { BOOST_PP_SEQ_HEAD(entries) = start) \
> BOOST_PP_SEQ_TAIL(entries) \
> (LAST_ ## name } name;) \
> ) \
> ) \

You can do it, but EXPR_IIF does not lazily evaluate its argument (the syntax
above is what EXPR_IIF would look like if it *did* lazily evaluate it argument).
In other words, when ENUMS is 0, SEQ_ENUM will still be invoked, but its results
will be discarded. For something like SEQ_ENUM, which is a cheap operation,
that is no big deal provided the call is still valid (even though the results
are discarded, it can still produce errors if the input is invalid). Other
constructs are significantly more expensive.

> 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) \
> ENUMS, \
> )( \
> (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!

Yes, you can certainly get rid of the hack. The above is equivalent, sans the
hack, to the code that you posted previously. The above is a higher-order
construct. The IIF is effectively returning a function. One of those functions
simply eats its argument. This is not abnormal in preprocessor code (to pass
around macro names as arguments).

> 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?

I don't know. I've used such things before (unsurprisingly, only when
debugging), but it isn't high on my priority list. If you use enumerations with
accompanying "print" functions often, then it certainly pays to generalize the
implementation. Have you seen There is an extended
enumeration proposal also
(, but I don't
know if it includes support for symbolic I/O. I'd read it to find out, but that
website is amazingly slow recently.

Paul Mensonides

Boost list run by bdawes at, gregod at, cpdaniel at, john at