C++11 scoped enumerators (enum class
syntax) do not convert to integers so they cannot be used directly as array indexes.
What's the best way to get the benefit of scoping when using them in this fashion?
I've provided a couple answers, but please add more ideas!
The original question related to using the enumeration as an array index. Instead of trying to turn the enumeration into an index for an array, build an array that accepts the enumeration as its index:
So now, with the earlier ducks example:
Had ducks values been capitalized differently, the size could default:
In addition to avoiding enum contortions, since the to-index conversion is hidden in the implementation, the enum doesn't risk erroneously becoming an integer at other points in your code, nor can you inadvertently index the array via integer.
EnumeratedArray is used in pianod2, in src/common. A more extensive version there includes template magic to only explicitly default-initialize plain-old datatypes, a constructor to initialize all elements to a specified value, and doc comments.
Why make it harder than it needs to be if your enumeration is consecutive?
Or if you must use templated functions...
Solution 1: Operator overloading.
This is my current favorite. Overload unary
operator+
andoperator++
to explicitly convert to integral type and increment within the enumerated type, respectively.Using an
enumeration_traits
template, overloads can be activated rather than copying boilerplate code. But the boilerplate is just a couple one-liners.Library code (templates, see below for non-template alternative):
User code:
Boilerplate code (if not using library, follows
enum
definition):Solution 2: Manual scoping.
Scoped enumerator syntax also works on unscoped (non
enum class
) enumerations, which do implicitly convert toint
. Hiding the enumeration inside a class or namespace and importing it withtypedef
orusing
makes it pseudo-scoped.But if multiple enumerations go into the same namespace, the enumerator names may collide, so you might as well use a class (or many namespaces).
This has some benefits. It works with C++03, but only with syntax
ducks_enum::count
. The enumerators are unscoped inside the struct, and it can be used as a base for any class that makes frequent use of the enumerators.Alternatively you can replace your
array
with amap
, which also means you can get rid of the maximum enum likecount
:I'm implementing a combination of DrTwox's solution plus the type safety of Potatoswatter's solution. Enumeration class must be explicitly defined to allow indexing, with size() also defined: