I use the following macros in my code: #define MAKE_FLAG_TYPE1(TYPE_NAME, F1) \ enum TYPE_NAME { F1 }; \ \ ::std::ostream& operator<<(::std::ostream& os, TYPE_NAME f) \ \ switch(f) \ { \ case F1: return os << #F1; \ } \ return os << "unknown"; \ } [2, 3 and 4 argument versions] #define MAKE_FLAG_TYPE5(TYPE_NAME, F1, F2, F3, F4, F5) \ enum TYPE_NAME { F1, F2, F3, F4, F5 }; \ \ ::std::ostream& operator<<(::std::ostream& os, TYPE_NAME f) \ { \ switch(f) \ { \ case F1: return os << #F1; \ case F2: return os << #F2; \ case F3: return os << #F3; \ case F4: return os << #F4; \ case F5: return os << #F5; \ } \ return os << "unknown"; \ } I wanted to try and do it with the Preprocessor library. It should be something like this: #include <boost/preprocessor/comma_if.hpp> #include <boost/preprocessor/repeat.hpp> #include <boost/preprocessor/repeat_2nd.hpp> #include <boost/preprocessor/inc.hpp> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/enum_params.hpp> #ifndef MAX_MAKE_FLAG_TYPE_PARAMS #define MAX_MAKE_FLAG_TYPE_PARAMS 10 #endif BOOST_PREPROCESSOR_REPEAT(MAX_MAKE_FLAG_TYPE, MAKE_FLAG_TYPE_AUX, _) #define MAKE_FLAG_TYPE_AUX(N,_) \ #define MAKE_FLAG_TYPE##N(TYPE_NAME,BOOST_PREPROCESSOR_ENUM_PARAMS(N, F)) \ enum TYPE_NAME { BOOST_PREPROCESSOR_ENUM_PARAMS(N, F) }; \ ::std::ostream& operator<<(::std::ostream& os, TYPE_NAME f) \ { \ switch(f) \ { \ BOOST_PREPROCESSOR_REPEAT_2ND(N, MAKE_FLAG_TYPE_AUX2, _) \ } \ return os << "unknown"; \ } #define MAKE_FLAG_TYPE_AUX2(N,_) \ case F##N: return os << BOOST_PREPROCESSOR_CAT(#, F##N); #undef MAKE_FLAG_TYPE_AUX #undef MAKE_FLAG_TYPE_AUX2 But then I looked at my code and clearly saw this won't do it. One of the problems is that by preprocessing I'll get things like: #define MAKE_FLAG_TYPE2(TYPE_NAME, F1, F2) enum [...] That won't work because of the spaces between the commas. And also I doubt BOOST_PREPROCESSOR_CAT(#, F##N) will work So, does anyone has any suggestions on how to implement my MAKE_FLAG_TYPE<N> macros using the Preprocessor library? Or is it just not possible? Thanks Gustavo Guerra
On 12/17/01 7:00 PM, "Gustavo Guerra" <gustavobt@mail.com> wrote:
So, does anyone has any suggestions on how to implement my MAKE_FLAG_TYPE<N> macros using the Preprocessor library? Or is it just not possible?
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. -- Darin
gustavo -- the only way is to run the preprocessor, cpp, explicitly. then you can run it twice to fully expand the code darin shows below, once explicitly and once implicitly by running the compiler. -- chuck Darin Adler wrote:
On 12/17/01 7:00 PM, "Gustavo Guerra" <gustavobt@mail.com> wrote:
So, does anyone has any suggestions on how to implement my MAKE_FLAG_TYPE<N> macros using the Preprocessor library? Or is it just not possible?
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.
-- Darin
-- |\_/\_.-'""``:-._ What is life without looking for . . `; -._ )-;-,_`) the next cute little bug to play with? v_,- _ ),(,.\ ``-' _.- _.,-_/ / ((.' -- chuck.siska@conexant.com `<}:.. ((,.-' ((,/
----- Original Message ----- From: "Darin Adler" <darin@bentspoon.com>
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
participants (3)
-
Chuck Siska
-
Darin Adler
-
Gustavo Guerra