Don't use operator ++
! What are you supposed to do if you have an enum like this?:
enum class other_enum : int
{
low = -3000,
fabada_asturiana = 0xfabada,
answer_to_life_universe_everything = 0b101010,
high = -low
};
As you can see, the values are not reachable increasing by one the previous one and don't even have a pattern; use iterators instead. Based on this answer:
// Shortcut to the enum map.
template <typename ENUM>
using enum_map = std::map<ENUM, const std::string>;
// The enum map.
template <typename ENUM>
enum_map<ENUM> enum_values{};
// Empty function to end the recursion.
void initialize() {}
// Initialize the enum map.
template <typename ENUM, typename ... args>
void initialize(const ENUM value, const char *name, args ... tail)
{
enum_values<ENUM>.emplace(value, name);
initialize(tail ...);
}
// Obtain the begin iterator to the enum
template <class ENUM, class = std::enable_if_t<std::is_enum<ENUM>{}>>
auto begin(ENUM &)
{
return enum_values<ENUM>.begin();
}
// Obtain the end iterator to the enum
template <class ENUM, class = std::enable_if_t<std::is_enum<ENUM>{}>>
auto end(ENUM &)
{
return enum_values<ENUM>.end();
}
The code above allows the user to create a map with enum values and a description string, it can be used like this:
int main()
{
initialize
(
white, "White",
red, "Red",
green, "Green",
blue, "Blue",
topleft, "Top Left",
topright, "Top Right",
bottomleft, "Bottom Left",
bottomright, "Bottom Right",
other_enum::low, "Lowest value",
other_enum::fabada_asturiana, "Typical Spanish",
other_enum::answer_to_life_universe_everything, "42",
other_enum::high, "Higher value"
);
...
return 0;
}
But the initialize
call is mandatory in order to make the whole thing work; isn't needed to put all the enums in one call though.
With all the code above, we can iterate the enums this way (Live demo):
for (const auto &v : colors{})
std::cout << v.first << '\n'; // Print values
for (const auto &v : corners{})
std::cout << v.second << '\n'; // Print names
for (const auto &v : other_enum{})
std::cout << (int)v.first << " = " << v.second << '\n'; // Print values & names
With this approach you can avoid the inheritance and work with the types directly. If you need to preserve the enum members order you can change the enum_map
to a container which preserves order or if you don't need to associate the value to a string the underlying container can be changed to a vector or a list.