I share your feelings, though some years ago I discovered the neat trick of "xmacros".
In a nutshell:
#define COLOR_LIST \
X( RED ) \
X( GREEN ) \
X( BLUE ) \
X( PURPLE )
enum Color
{
#define X(code) code,
COLOR_LIST
#undef X
};
static const char* colorNames[] =
{
#define X(code) #code,
COLOR_LIST
#undef X
};
You can even make it cleaner and store more metadata:
// --- color.def
X( RED, "Red", 0xFF0000 )
X( GREEN, "Green", 0x00FF00 )
X( BLUE, "Blue", 0x0000FF )
// --- color.h
enum Color
{
#define X(code,name,mask) code,
# include "color.def"
#endif
};
static const char* colorNames[] =
{
#define X(code,name,mask) name,
# include "color.def"
#undef X
};
static unsigned int colorMasks[] =
{
#define X(code,name,mask) mask,
# include "color.def"
#undef X
};