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:
- each enumeration needs an initialization value
- fixed to 7 enumeration values
For a more generalized usage I have two questions. Especially the second one would increase the usability enormously.
Any here my questions:
- How can I avoid to define a initialization value for each enumeration value?
(like in a real enumeration) - Any ideas to generalize the #define to work with any number of values?
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:
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.