I'm a big fan of C++'s strong-typing features and what I like the most is to use enumerations while dealing with limited sets of data.
But enumerations lack some useful features, for example operators:
enum class Hex : int
{
n00, n01, n02, n03,
n04, n05, n06, n07,
n08, n09, n10, n11,
n12, n13, n14, n15
};
for (Hex h = Hex::n0; h <= Hex::n15; ++h) // Oops! no 'operator ++'
{ /* ... */ }
Is easy to get rid of the lack of operators creating a free operator on the same scope:
Hex &operator ++(Hex &h)
{
int r = static_cast<int>(Hex);
h = static_cast<Hex>(r + 1);
return h;
}
for (Hex h = Hex::n0; h <= Hex::n15; ++h) // Now the '++h' works!
{
std::cout << std::dec << int(h) << ": "
<< std::hex << int(h) << '
';
}
But this approach is more a nuisance than a solution, because it can break the value limitation of the enumeration: applying ++h
while h
equals to Hex::n15
will set h to he value 16, wich is out of the Hex
scope of values while h
is still of the type Hex
!, This problem is more evident in other enumerations:
enum class Prime : int
{
n00 = 2, n01 = 3, n02 = 5, n03 = 7,
n04 = 11, n05 = 13, n06 = 17, n07 = 19,
n08 = 23, n09 = 29, n10 = 31, n11 = 37,
n12 = 41, n13 = 43, n14 = 47, n15 = 53
};
Prime &operator ++(Prime &p)
{
// How to implement this?! will I need a lookup table?
return p;
}
This problem was a surprise for me; I was betting that storing an incorrect value into an enumeration value will throw an exception. So, for now I was wondering if there's an elegant way to deal with this enumeration's weaknesses, the goals I want to achieve are:
- Find a comfortable way to use enumeration values in loops.
- Ensuring enumation data consistency between operations.
Additional questions:
- Is there a reason for not throwing an exception when an enumeration data gets a value that is out of its possible values?
- There is a way to deduce the type associated with an enumeration class?, the
int
type in the enumerations Hex
and Prime
.
See Question&Answers more detail:
os