I want to use a C++ enum class as std:array
index without calling an explicit cast, when I want to refer to a specific index.
I furthermore use a typedef
for a fixed sized std::array
.
typedef std::array<int, 3> MyType;
enum class MyEnum {
ENUMERATOR0 = 0,
ENUMERATOR1 = 1,
ENUMERATOR2 = 2,
};
So instead of using:
MyType my_type = {0};
my_type[static_cast<int>(MyEnum::ENUMERATOR0)] = 42;
I want to use:
my_type[MyEnum::ENUMERATOR0] = 42;
Therefore, I assume it is required to overload the subscript operator of my MyType
(std::array
) type. However, I couldn't figure out, how to overload the subscript operator in my case. For simplicity reasons, I would like to avoid using a class instead of the typedef.
How can I do this?
In C++, I can define a enum and use the enum as the array index.
You can't do that. A C enum is not much more than a bunch of constants. There's no type-safety or reflection that you might get in a C# or Java enum . Save this answer.
Enums are value types (usually Int32). Like any integer value, you can access an array with their values. Enum values are ordered starting with zero, based on their textual order. MessageType We see the MessageType enum, which is a series of int values you can access with strongly-typed named constants.
enum class holds an integral value just like a regular enum so you can safely pass it by value without any overhead. Notice that compiler may sometimes optimize pass by reference as well by replacing it with pass by value. But passing by reference may result in some overhead when such an optimization is not applied.
I found a good solution for this. You can both use enum classes as indices in your arrays and also get the added benefit of ensuring type safety (i.e. preventing use of the wrong enum type as indices) by subclassing std::array and overriding its operator[] method.
Here is an example.
You can define enum_array like this:
#include <array>
// this is a new kind of array which accepts and requires its indices to be enums
template<typename E, class T, std::size_t N>
class enum_array : public std::array<T, N> {
public:
T & operator[] (E e) {
return std::array<T, N>::operator[]((std::size_t)e);
}
const T & operator[] (E e) const {
return std::array<T, N>::operator[]((std::size_t)e);
}
};
And you can use it like this:
int main() {
enum class Fruit : unsigned int {
Apple,
Kiwi
};
enum class Vegetable : unsigned int {
Carrot,
Potato
};
// Old way:
std::array<int, 3> old_fruits;
std::array<int, 3> old_veggies;
old_fruits[(int)Fruit::Apple] = 3; // compiles but "ugly"
old_veggies[(int)Vegetable::Potato] = 7; // compiles but "ugly"
old_fruits[(int)Vegetable::Potato] = 3; // compiles but shouldn't compile!
old_fruits[2] = 6; // compiles but may or may not be desirable
// New way:
enum_array<Fruit, int, 3> fruits;
enum_array<Vegetable, int, 3> veggies;
fruits[Fruit::Apple] = 3;
veggies[Vegetable::Potato] = 7;
// fruits[Vegetable::Potato] = 3; // doesn't compile :)
// fruits[2] = 6; // doesn't compile
// fruits[(int)Fruit::Apple] = 3; // doesn't compile
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With