I have a #define with generates a enum class and a corresponding output operator the the generated enum class.(see below)
#define ENUM(N, T, N1, V1, N2, V2, N3, V3, N4, V4, N5, V5, N6, V6, N7, V7)\
enum class N : T {\
N1 = V1,\
N2 = V2,\
N3 = V3,\
N4 = V4,\
N5 = V5,\
N6 = V6,\
N7 = V7,\
};\
std::ostream &operator <<(std::ostream &os, const N val); /* declare function to avoid compiler warning */\
std::ostream &operator <<(std::ostream &os, const N val) {\
switch (val) {\
case N::N1:\
os << #N1;\
break;\
case N::N2:\
os << #N2;\
break;\
case N::N3:\
os << #N3;\
break;\
case N::N4:\
os << #N4;\
break;\
case N::N5:\
os << #N5;\
break;\
case N::N6:\
os << #N6;\
break;\
case N::N7:\
os << #N7;\
break;\
}\
if (sizeof(T) == 1) {\
os << '(' << static_cast<int>(val) << ')';\
} else {\
os << '(' << static_cast<T>(val) << ')';\
}\
return os;\
}
It can be used like here in this example:
#include <cstdlib>
#include <iostream>
#include <ostream>
ENUM(Weekdays, unsigned char, Monday, 10, Tuesday, 12, Wednesday, 14, Thursday, 16, Friday, 18, Saterday, 100, Sunday, 101)
int main(const int /*argc*/, const char *const /*argv*/[]) {
Weekdays test = Weekdays::Monday;
std::cout << test << std::endl;
std::cout << Weekdays::Tuesday << std::endl;
std::cout << Weekdays::Sunday << std::endl;
return EXIT_SUCCESS;
}
here the generated output:
Monday(10)
Tuesday(12)
Sunday(101)
My solution has some restrictions:
For a more generalized usage I have two questions. Especially the second one would increase the usability enormously.
Any here my questions:
I'm waiting for your comments to my code and suggestions for improvement.
Rainer
Sticking relatively close what you have right now, you can take advantage of the BOOST_PP_SEQ_FOR_EACH macro from Boost.Preprocessor, which could look something like this:
#include <boost/preprocessor.hpp>
#define ENUM_FIELD(I,_,F) F,
#define ENUM_OUTPUT_CASE(I,N,F) case N::F: os << BOOST_PP_STRINGIZE(F); break;
#define ENUM(N, T, ARGS) \
enum class N : T {\
BOOST_PP_SEQ_FOR_EACH(ENUM_FIELD,N,ARGS)\
};\
std::ostream &operator <<(std::ostream &os, const N val) {\
switch (val) {\
BOOST_PP_SEQ_FOR_EACH(ENUM_OUTPUT_CASE,N,ARGS)\
}\
\
os << '(' << static_cast<int>(val) << ')';\
return os;\
}
ENUM(Weekdays, unsigned char, (Monday)(Tuesday)(Wednesday)(Thursday)(Friday)(Saturday)(Sunday))
That removes both the duplication and possibility of supplying the values. The whole thing is shorter, arguably at the cost of making it less readable and potentially harder to debug – I won't weigh in on the pro's and cons of using macros like these.
Note that I've changed the way arguments are passed to the ENUM macro: this is now a Boost.Preprocessor sequence. You should be able to pass up to 256 elements; see the documentation for more information and more macros that work on sequences.