Этот вопрос пришел мне в голову, когда у меня было что-то вроде
enum Folders {FA, FB, FC};
и хотел создать массив контейнеров для каждой папки:
ContainerClass*m_containers[3];
....
m_containers[FA] = ...; // etc.
(Использование карты это гораздо элегантнее использования: std::map<Folders, ContainerClass*> m_containers;
)
Но вернемся к моему первоначальному вопросу: что, если я не хочу жестко программировать размер массива, есть ли способ выяснить, сколько элементов находится в папках? (Не полагаясь, например, на FC
то, чтобы быть последним элементом в списке, который позволил бы что-то вроде, ContainerClass*m_containers[FC+1]
если я не ошибаюсь.)
c++
count
enumeration
Fuenfundachtzig
источник
источник
int(FA) | int(FB) | int (FC)
это также допустимое значениеFolders
переменной. Если вы выбираете размерm_containers
так, чтобы любаяFolders
переменная была допустимым индексом, этого[FC+1]
было бы недостаточно.Ответы:
На самом деле нет хорошего способа сделать это, обычно вы видите дополнительный элемент в перечислении, т.е.
Итак, вы можете:
Хотя все равно не очень хорошо.
Но, конечно, вы понимаете, что просто количество элементов в перечислении небезопасно, например,
количество элементов будет 4, но целочисленные значения значений перечисления будут выходить за пределы диапазона индекса массива. Использование значений перечисления для индексации массива небезопасно, вам следует рассмотреть другие варианты.
edit: как и просили, сделал специальную запись больше.
источник
Для C ++ доступны различные методы безопасного перечисления , и некоторые из них (например, предложенный, но никогда не представленный Boost.Enum ) включают поддержку получения размера перечисления.
Самый простой подход, который работает как в C, так и в C ++, - принять соглашение об объявлении значения ... MAX для каждого из ваших типов перечислений:
Изменить : Что касается
{ FA, FB, FC, Folders_MAX = FC}
против{FA, FB, FC, Folders_MAX]
: я предпочитаю устанавливать значение ... MAX на последнее допустимое значение перечисления по нескольким причинам:Folders_MAX
дает максимально возможное значение перечисления).Folders_MAX = FC
выделяется среди других записей немного больше (что немного затрудняет случайное добавление значений перечисления без обновления максимального значения, проблема, на которую ссылается Мартин Йорк).источник
enum Folders { FA, FB, FC, Folders_MAX }; ContainerClass *m_containers[Folders_MAX];
:?struct SomeEnum { enum type {FA, FB, FC, NB__};};
Как насчет черт в стиле STL? Например:
написать
специализация (возможно, constexpr, если вы используете c ++ 11). Затем в вашем тестовом коде укажите любые статические утверждения для поддержания ограничений, которые std :: numeric_limits :: max () = last_item.
источник
std::numeric_limits<enum Foo>::max()
всегда возвращает ноль ... (см. вопрос для связанного ответа) Протестировано на обычных enums (enum Foo { ... }
), enums (enum class Foo : uint8_t { ... }
) с подсказками типа с gcc 5.2.0 @ Linux и MinGW 4.9.3 @ Windows.std::numeric_limits<std::underlying_type<Foo>::type>::max()
, он возвращает максимальное значение базового типа, т.е. 0xFFFFFFFF для 32-битных целых чисел, что бесполезно в этом контексте.)namespace gx { enum struct DnaNucleobase : char { A, C, G, T }; }
Затем:namespace std { template<> struct numeric_limits<enum ::gx::DnaNucleobase> { typedef enum ::gx::DnaNucleobase value_type; static constexpr value_type max() { return value_type::T; } (...)
Иstd::cout << std::numeric_limits<::gx::DnaNucleobase>::max() << std::endl;
печатает ожидаемый результат. Протестировано с использованием версий gcc 5.2.1 и 4.8 / 4.9.numeric_limits<T>::max()
. Единственное, что функция могла бы разумно вернуть, - это наивысшее перечислимое значение. Он вернется2
, но OP (в данном конкретном случае) должен вернуть его3
. Если у вас есть значения, отличные от значений по умолчанию для enum (FB = 2057
), все ставки отключены, и невозможно даже+ 1
взломать ошибку «off-by-one». Если бы былоnumeric_limits<T>::number_of_elements_of_the_set()
(или более короткое имя), его можно было бы использовать без двусмысленности.Добавьте в конец перечисления запись с именем Folders_MAX или что-то подобное и используйте это значение при инициализации массивов.
источник
Мне нравится использовать перечисления в качестве аргументов своих функций. Это простой способ предоставить фиксированный список «вариантов». Проблема с ответом, получившим наибольшее количество голосов, заключается в том, что с его помощью клиент может указать «недопустимый вариант». В качестве дополнительного решения я рекомендую сделать по сути то же самое, но использовать константу int вне перечисления, чтобы определить их количество.
Это неприятно, но это чистое решение, если вы не меняете перечисление без обновления константы.
источник
Я действительно не вижу никакого способа действительно получить количество значений в перечислении в C ++. Любое из упомянутых выше решений работает до тех пор, пока вы не определяете значение своих перечислений, если вы определяете свое значение, которое может возникнуть в ситуациях, когда вы создаете слишком большие или слишком маленькие массивы
в этом примере результат будет создавать массив из 3 элементов, когда вам нужен массив из 5 элементов
в этом примере результат будет создавать массив из 301 элемента, когда вам нужен массив из 5 элементов
Лучший способ решить эту проблему в общем случае - это перебрать ваши перечисления, но, насколько я знаю, это еще не в стандарте
источник