Boost logo

Boost Users :

From: Gustavo Guerra (gustavobt_at_[hidden])
Date: 2001-12-18 21:22:53


----- Original Message -----
From: "Darin Adler" <darin_at_[hidden]>
> The underlying issue is that you can't use a macro to define a macro. That
> just how the C and C++ language macros work.
>
> So
>
> #define X #define Y 1
> X
>
> will not allow you to define Y by invoking X. You'll just get a syntax
error
> when the compiler sees the "#define" after expanding X.
>
> I think the answer then is that it's just not possible, although there
still
> may be some creative way to use the PREPROCESSOR library to help with what
> you are trying to do.
>

I has hoping that there was some obscure trick to make the preprocessor
reprocess that part, but I guess not.
So, I tried this, based on http://groups.yahoo.com/group/boost/message/21743

#include <boost/preprocessor/tuple.hpp>
#include <boost/preprocessor/logical/not.hpp>
#include <boost/preprocessor/comma.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/if.hpp>
#include <boost/preprocessor/identity.hpp>
#include <boost/preprocessor/empty.hpp>

//---------------------- by Vesa
Karvonen: -----------------------------------

#define BOOST_PREPROCESSOR_LIST_NIL (_,_,0)

#define BOOST_PREPROCESSOR_LIST_CONS(H,T) (H,T,1)

#define BOOST_PREPROCESSOR_LIST_IS_CONS(L)
BOOST_PREPROCESSOR_TUPLE_ELEM(3,2,L)

#define BOOST_PREPROCESSOR_LIST_IS_NIL(L)
BOOST_PREPROCESSOR_NOT(BOOST_PREPROCESSOR_TUPLE_ELEM(3,2,L))

#define BOOST_PREPROCESSOR_LIST_HEAD(L)
BOOST_PREPROCESSOR_TUPLE_ELEM(3,0,L)

#define BOOST_PREPROCESSOR_LIST_TAIL(L)
BOOST_PREPROCESSOR_TUPLE_ELEM(3,1,L)

//---------------------- by me: -------------------------

#define BOOST_PREPROCESSOR_LIST1(X) BOOST_PREPROCESSOR_LIST_CONS(X,\
                                          BOOST_PREPROCESSOR_LIST_NIL)

#define BOOST_PREPROCESSOR_LIST2(X,Y) BOOST_PREPROCESSOR_LIST_CONS(X,\
                                          BOOST_PREPROCESSOR_LIST_CONS(Y,\
                                          BOOST_PREPROCESSOR_LIST_NIL))

#define BOOST_PREPROCESSOR_LIST3(X,Y,Z) BOOST_PREPROCESSOR_LIST_CONS(X,\
                                          BOOST_PREPROCESSOR_LIST_CONS(Y,\
                                          BOOST_PREPROCESSOR_LIST_CONS(Z,\
                                          BOOST_PREPROCESSOR_LIST_NIL)))

#define BOOST_PREPROCESSOR_LIST4(X,Y,Z,W) BOOST_PREPROCESSOR_LIST_CONS(X,\
                                          BOOST_PREPROCESSOR_LIST_CONS(Y,\
                                          BOOST_PREPROCESSOR_LIST_CONS(Z,\
                                          BOOST_PREPROCESSOR_LIST_CONS(W,\
                                          BOOST_PREPROCESSOR_LIST_NIL))))

#define BOOST_PREPROCESSOR_LIST_IS_SIZE_1(L) \
  BOOST_PREPROCESSOR_LIST_IS_NIL(BOOST_PREPROCESSOR_LIST_TAIL(L))

#define BOOST_PREPROCESSOR_LIST_FOR_EACH(LIST,P) \
  BOOST_PREPROCESSOR_IF(BOOST_PREPROCESSOR_LIST_IS_NIL(LIST), \
                        P(BOOST_PREPROCESSOR_LIST_HEAD(LIST)), \

BOOST_PREPROCESSOR_LIST_FOR_EACH(BOOST_PREPROCESSOR_LIST_TAIL(LIST), P))

#define BOOST_PREPROCESSOR_LIST_ENUMERATE(LIST) \
  BOOST_PREPROCESSOR_IF(BOOST_PREPROCESSOR_LIST_IS_SIZE_1(LIST), \
                        BOOST_PREPROCESSOR_LIST_HEAD(LIST), \

BOOST_PREPROCESSOR_LIST_ENUMERATE(BOOST_PREPROCESSOR_LIST_TAIL(LIST)) \
                        BOOST_PREPROCESSOR_COMMA)

#define MAKE_FLAG_TYPE(TYPE_NAME, LIST) \
  enum TYPE_NAME { BOOST_PREPROCESSOR_LIST_ENUMERATE(LIST) }; \
::std::ostream& operator<<(::std::ostream& os, TYPE_NAME f) \
{ \
  switch(f) \
  { \
    BOOST_PREPROCESSOR_FOR_EACH(LIST, MAKE_FLAG_TYPE_AUX) \
  } \
  return os << "unknown"; \
}

#define MAKE_FLAG_TYPE_AUX(ELEM) \
  case ELEM: return os << BOOST_PREPROCESSOR_STRINGIZE(ELEM);

This way, instead of writing something like this:

    MAKE_FLAG_TYPE4(event_type, read_event, write_event, timeout_event,
error_event)

I would have to write:

    MAKE_FLAG_TYPE(event_type, BOOST_PREPROCESSOR_LIST4(read_event,
write_event, timeout_event, error_event))

But this still doesn't work. Neither
BOOST_PREPROCESSOR_LIST_FOR_EACH(LIST,P) nor
BOOST_PREPROCESSOR_LIST_ENUMERATE(LIST) work. I didn't even bother to test
the rest. The problem seems to be that BOOST_PREPROCESSOR_IF doesn't call
the else part. When I look at the preprocessed code of:

    BOOST_PREPROCESSOR_LIST_ENUMERATE(BOOST_PREPROCESSOR_LIST4(a,b,c,d))

I see something like:

     BOOST_PREPROCESSOR_LIST_ENUMERATE((b,(c,(d,(_,_,0),1),1),1))
BOOST_PREPROCESSOR_COMMA

Although when I use

    BOOST_PREPROCESSOR_LIST_ENUMERATE(BOOST_PREPROCESSOR_LIST1(a))

I get

    a

like expected

What am I doing wrong?

Gustavo Guerra


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net