
-----Original Message----- [mailto:boost-bounces@lists.boost.org] On Behalf Of Arias Brent-P96059
I've invented a printable enum, based on the Boost preprocessor programming lib. But although the printable enum works, I think my efforts revealed a bug in Boost.
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++.
The BOOST_PP_SEQ_ENUM preprocessor macro doesn't work with the empty "false" result of BOOST_PP_EXPR_IIF. This has forced me to do hacks like this:
#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? That is roughly equivalent to doing something like: #include <algorithm> #include <iostream> #include <vector> void print(int x) { std::cout << x << ' '; return; } extern bool flag; int main(int argc, char* argv[]) { int init[] = { 1, 2, 3, 4, 5 }; std::vector<int> v(init, init + sizeof(init) / sizeof(int)); std::for_each((flag ? v.begin() : v.end()), v.end(), &print); // ^^^^^^^^^^^^^^^^^^^^^^^^^^ return 0; } Instead of: if (flag) std::for_each(v.begin(), v.end(), &print); The same thing applies at the preprocessor level--if you want to conditionally enumerate a sequence, then invoke the enumeration primitive conditionally instead of attempting to unilaterally enumerating a sequence while trying to conditionally make that enumeration benign. #include <boost/preprocessor/control/iif.hpp> #include <boost/preprocessor/seq/enum.hpp> #include <boost/preprocessor/seq/seq.hpp> #include <boost/preprocessor/tuple/eat.hpp> #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;) \ ) \ /**/ RANT: If preprocessors worked as they should, I could guarantee lazy semantics in if-like constructs. With lazy semantics in this context, the above would be: #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;) \ ) \ ) \ /**/
BOOST_PP_EXPR_IIF and thus avoid the eye-sore. But the hack was necessary, as I said before, because BOOST_PP_SEQ_ENUM does not elogantly handle the empty "false" result of BOOST_PP_EXPR_IIF.
C++ does not elegantly handle empty macro arguments. There is literally *nothing* I can do about that. Regards, Paul Mensonides