Как мы должны использовать класс enum для индексации (или нам лучше этого избежать)? - PullRequest
2 голосов
/ 07 января 2020

Скажем, у нас есть enum тип foo, который мы хотим использовать для индексации массива arr со стати c размера.

Если мы хотим использовать enum class для этого , мы могли бы попробовать это так:

enum class foo
{
    a,
    b,
    c,
    count
};

std::array<T, static_cast<int>(foo::count)> arr;

Однако, поле count взломано. Можем ли мы получить число полей foo более элегантным способом?

В любом случае, что действительно плохо, так это то, что нам необходим доступ к массиву также с помощью static_cast: arr[static_cast<int>(foo::a)].

Конечно, мы могли бы написать собственную функцию «at» (см. https://www.fluentcpp.com/2019/01/15/indexing-data-structures-with-c-scoped-enums/) или предоставить класс «enum_array» (см. { ссылка }), но оба решения как-то сложны, и мы могли бы лучше отказаться и использовать простое std::array<T, int> вместо ...

Однако гораздо удобнее читать arr[foo::a] вместо arr[0], где нам всегда нужно помните, что означает индекс 0 в последнем.

Можем ли мы сделать лучше?

Ответы [ 2 ]

3 голосов
/ 07 января 2020

Нет, не совсем.

Есть много предложений, которые позволяют ставить c отражение значений перечисления. Пока нет ни одного в C ++.

Я имею в виду, что вы можете сделать:

namespace foo {
  enum value {
    a,b,c,count
  };
}

, тогда преобразование в int является неявным, и вы не загрязняете содержащееся пространство имен.

Решение здесь довольно близко к 0 издержек и позволяет использовать перечисления (и только перечисления) в качестве ключей для [].

Таким образом, вы получаете:

enum_array<foo, T> arr;

и arr ведут себя так, как вы хотите.

2 голосов
/ 07 января 2020

В качестве частичного решения вы можете определить

constexpr std::underlying_type_t<foo> operator*(foo f) {
    return static_cast<std::underlying_type_t<foo>>(f);
}

, а затем написать

int bar(std::array<int, *foo::count>& arr) {
    return arr[*foo::b];
}

Демо

...