(Как) я могу сосчитать предметы в перечислении?

Этот вопрос пришел мне в голову, когда у меня было что-то вроде

enum Folders {FA, FB, FC};

и хотел создать массив контейнеров для каждой папки:

ContainerClass*m_containers[3];
....
m_containers[FA] = ...; // etc.

(При использовании карт гораздо элегантнее использовать: std::map m_containers;)

Но вернемся к моему первоначальному вопросу: что, если я не хочу жестко задавать размер массива, есть ли способ выяснить, сколько элементов в папках? (Не полагаясь на э. г. FC - последний элемент в списке, который может позволить что-то вроде ContainerClass*m_containers[FC+1], если я не ошибаюсь. )

вопрос задан 20.01.2010
fuenfundachtzig
2894 репутация

6 ответов


  • 101 рейтинг

    На самом деле нет хорошего способа сделать это, обычно вы видите дополнительный элемент в перечислении, т.е. е.

    enum foobar {foo, bar, baz, quz, FOOBAR_NR_ITEMS};
    

    Итак, вы можете сделать:

    int fuz[FOOBAR_NR_ITEMS];
    

    Все еще не очень хорошо все же.

    Но, конечно, вы понимаете, что только количество элементов в перечислении небезопасно, учитывая e. г.

    enum foobar {foo, bar = 5, baz, quz = 20};
    

    количество элементов будет равно 4, но целочисленные значения значений перечисления будут выходить за пределы диапазона индекса массива. Использование перечислимых значений для индексации массива небезопасно, вы должны рассмотреть другие варианты.

    редактировать: по запросу, заставил специальную запись выделяться больше.

    ответ дан wich, с репутацией 12062, 20.01.2010
  • 28 рейтинг

    Для C ++ доступны различные типобезопасные перечислимые методы , и некоторые из них (например, предложенное, но никогда не представленное повышение . Enum ) включает поддержку для получения размера enum.

    Простейший подход, который работает как в C, так и в C ++, заключается в принятии соглашения об объявлении a. , , Максимальное значение для каждого из типов перечислений:

    enum Folders { FA, FB, FC, Folders_MAX = FC };
    ContainerClass *m_containers[Folders_MAX + 1];
    ....
    m_containers[FA] = ...; // etc.
    

    Редактировать : Относительно { FA, FB, FC, Folders_MAX = FC} против {FA, FB, FC, Folders_MAX]: Я предпочитаю устанавливать. , , Максимальное значение до последнего допустимого значения перечисления по нескольким причинам:

    1. Имя константы технически более точно (так как Folders_MAX дает максимально возможное значение enum).
    2. Лично я чувствую, что Folders_MAX = FC выделяется из других записей немного больше (что усложняет случайное добавление значений перечисления без обновления максимального значения, проблема, на которую ссылается Мартин Йорк).
    3. GCC включает полезные предупреждения, такие как «значение перечисления, не включенное в переключатель» для кода, такого как следующий. Letting Folders_MAX == FC + 1 снимает эти предупреждения, так как в итоге вы получаете кучу. , , Максимальные значения перечисления, которые никогда не должны быть включены в switch.
    switch (folder) 
    {
      case FA: ...;
      case FB: ...;
      // Oops, forgot FC!
    }
    
    ответ дан Josh Kelley, с репутацией 40777, 20.01.2010
  • 5 рейтинг

    Как насчет черт в стиле STL? Например:

    enum Foo
    {
        Bar,
        Baz
    };
    

    написать

    std::numeric_limits::max()
    
    Специализация

    (возможно, constexpr, если вы используете c ++ 11). Затем в своем тестовом коде предоставьте все статические утверждения для поддержки ограничений, которые std :: numeric_limits :: max () = last_item.

    ответ дан Wojciech Migda, с репутацией 357, 23.12.2014
  • 3 рейтинг

    Добавьте в конец вашего перечисления запись с именем Folders_MAX или что-то подобное и используйте это значение при инициализации ваших массивов.

    ContainerClass* m_containers[Folders_MAX];
    
    ответ дан Kevin Doyon, с репутацией 1984, 20.01.2010
  • 1 рейтинг

    Я действительно не вижу способа действительно получить количество значений в перечислении в C ++. Любое из упомянутых выше решений работает, если вы не определите значение своих перечислений, если вы определите свое значение, которое может возникнуть в ситуациях, когда вы создаете слишком большие или слишком маленькие массивы

    enum example{ test1 = -2, test2 = -1, test3 = 0, test4 = 1, test5 = 2 }
    

    в этом о примерах результат будет создавать массив из 3 элементов, когда вам нужен массив из 5 элементов

    enum example2{ test1 , test2 , test3 , test4 , test5 = 301 }
    

    в этом о примерах результат будет создавать массив из 301 элементов, когда вам нужен массив из 5 элементов

    Лучший способ решить эту проблему в общем случае - это перебрать ваши перечисления, но это не в стандарте, насколько я знаю

    ответ дан does_not_exist, с репутацией , 12.01.2015
  • 1 рейтинг

    Мне нравится использовать перечисления в качестве аргументов моих функций. Это простой способ предоставить фиксированный список «опций». Проблема с ответом, получившим наибольшее количество голосов, заключается в том, что с его помощью клиент может указать «недопустимую опцию». В качестве побочного результата я рекомендую делать по существу то же самое, но использовать константу int вне перечисления, чтобы определить их количество.

    enum foobar { foo, bar, baz, quz };
    const int FOOBAR_NR_ITEMS=4;
    

    Это не приятно, но это чистое решение, если вы не измените enum без обновления константы.

    ответ дан BuvinJ, с репутацией 3398, 13.11.2017