0

Is there a way to use enum elements to index into an array in a way that minimizes indexing errors.

Example:

enum class Index : int {
    Foo, Bar, Koo
};

static const int Values[] = { 42, 7, 3 };

constexpr int GetValue(Index i) {
    return Values[int(i)];
}

auto v = GetValue(Index::Foo);

The problem with the above is that modifying either Index or Values may cause indexes to point to wrong values, and such errors would not be detected by the compiler.

Dess
  • 2,064
  • 19
  • 35
  • Can we assume things are a bit more dynamic, so trivialities like `enum class Index : int { Foo = 42, Bar = 7, Koo = 3};` aren't viable? – user4581301 Apr 17 '23 at 22:20
  • or just `constexpr int Foo = 42; constexpr int Bar=7; constexpr int Koo=3;`? – Mooing Duck Apr 17 '23 at 22:22
  • Honestly, the more I experiment with this, the more it sounds like you don't have an array of ints. – Mooing Duck Apr 17 '23 at 22:36
  • http://coliru.stacked-crooked.com/a/0ebf7e7c72fa6428 is as close as I could get, but it's not perfect. It lets you add an `Index` without initializing it's array value, and then you can access out-of-bounds after that :( – Mooing Duck Apr 17 '23 at 22:42
  • Choosing ints for the Values is just for the example code. In reality, each entry is a complex object with lots of init data. Also, there are alot of entries. – Dess Apr 17 '23 at 23:06
  • I was looking for something like the following, but it's not supported by C++/MSVC: https://stackoverflow.com/questions/17581074/explicit-indexes-in-c-array-literals – Dess Apr 17 '23 at 23:15
  • 2
    Is there a reason not to use a map? – Mikel F Apr 18 '23 at 00:07
  • For reducing errors when iterating over elements of an array, it's better to not use indices at all - for example, iterating over ranges specified in terms of `begin()` and `end()` iterators of standard containers. For having alternative names for particular elements in a container, there are maps. – Peter Apr 18 '23 at 00:31
  • @MikelF: I was asking for this in the general case, because I wanted to know to do it for builtin arrays. But, the const map version does work for my usecase. So, it's good that you pointed that out. – Dess Apr 18 '23 at 08:54

1 Answers1

0

Setting a final enum value to count total number of enumerations will do the trick, assuming your enumerations are 0, 1, 2, ... etc.

enum class Index : int {
    Foo,
    Bar,
    Koo,
    NUM_INDICES // 3
};

static const int Values[Index::NUM_INDICES] = { 42, 7, 3 };
guard3
  • 823
  • 4
  • 13
  • 1
    Not 100%. It can't ensure the right number is at the right index, and if you leave out numbers in `Values` they get zero padded at the end. About all this can do is error out if too many values are supplied and maybe issue a warning if too few. – user4581301 Apr 17 '23 at 22:33
  • 1
    Also missing a cast. Can't use a member of an enum class as a array size without a bit of help. – user4581301 Apr 17 '23 at 22:35
  • Remember that `enum` declarations don't have to be contiguous; there can be gaps. – Thomas Matthews Apr 18 '23 at 00:34
  • Since your enum is declared as an integer, one can insert "Kaz = -1`, to the top of the list for some interesting behavior. – Thomas Matthews Apr 18 '23 at 00:35