Thanks to Sebastian Mestre (who commented on my previous post), I learned something new today. The X macro makes the enum
to string
code much… well, perhaps not cleaner, but shorter. It also solves the problem of having to update the code in 2 places: first in the enum
itself, second in the enum
to string
map.
Without further ado, I present to you the X macro:
And the complete implementation goes something like this:
#include <iostream>
#define MY_ENUM \
X(V1) \
X(V2) \
X(V3)
#define X(name) name,
enum MyEnum
{
MY_ENUM
};
#undef X
constexpr const char* MyEnumToString(MyEnum e) noexcept
{
#define X(name) case(name): return #name;
switch(e)
{
MY_ENUM
}
#undef X
}
int main(int argc, char** argv)
{
std::cout << MyEnumToString(V1) << std::endl;
std::cout << MyEnumToString(V2) << std::endl;
std::cout << MyEnumToString(V3) << std::endl;
return 1;
}
In this version, we only have to update the MY_ENUM
macro. The rest is taken care of by the preprocessor.
Update
Here’s the same approach that works with strongly typed enum
s:
#include <iostream>
#define MY_ENUM \
X(V1) \
X(V2) \
X(V3)
#define X(name) name,
#define MY_ENUM_NAME MyEnum
enum class MY_ENUM_NAME : char
{
MY_ENUM
};
#undef X
constexpr const char* MyEnumToString(MyEnum e) noexcept
{
#define X(name) case(MY_ENUM_NAME::name): return #name;
switch(e)
{
MY_ENUM
}
#undef X
}
int main(int argc, char** argv)
{
std::cout << MyEnumToString(MyEnum::V1) << std::endl;
std::cout << MyEnumToString(MyEnum::V2) << std::endl;
std::cout << MyEnumToString(MyEnum::V3) << std::endl;
return 1;
}