I'm never again hand-writing an my_enum_to_str routine.
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
}; #undef X
when you're done.#define SQ(x) x*x
cout << SQ(2) // prints 4 since 2*2 = 4
cout << SQ(1+3) // prints 7 since 1+3*1+3 = 7
Macros are pretty much entirely unnecessary and should be avoided. Compilers inline nowadays, so you don’t really gain anything from using a macro when you could have just made a function that gives you type safety and intuitive behavior. If you are trying to define constants, use const, enum, or enum classes. If you are trying to define multiple versions of the same function, use polymorphism or templates. If you are trying to wrap around arbitrary code, use lambdas.
#define SQ(x) ((x)*(x))
set off my C spidey senses. I use them even for constants in pound defines just to be consistent.That being said, there are benefits, like the type safety listed being one of them. No weird cast to void* and go to town on raw memory shenanigans you would have to do to use functions in intrusive collections in C.
#define SQ(x) ((x)*(x))
If you can assume a compiler with statement expressions and typeof (gcc, clang, probably icc in this case):
#define SQ(x) ({ typeof(x) x_ = (x); x_ * x_ })
If not (MSVC++) then best of luck.
Anyway I 100% agree people way, way overuse macros. Very often a static inline function is a better trade-off.
Apart from being a pain in the ass to write (don't forget your escape slashes (\) for line endings!), using these macros makes debugging much harder - you no longer have a stack trace (although GDB is fairly smart about this, it's still less than ideal).