web-dev-qa-db-fra.com

(Comment) puis-je compter les éléments dans une énumération?

Cette question m’est venue à l’esprit lorsque j’avais quelque chose comme

enum Folders {FA, FB, FC};

et je voulais créer un tableau de conteneurs pour chaque dossier:

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

(En utilisant des cartes, il est beaucoup plus élégant d'utiliser: std::map<Folders, ContainerClass*> m_containers;)

Mais pour revenir à ma question initiale: si je ne veux pas coder en dur la taille du tableau, existe-t-il un moyen de déterminer le nombre d'éléments contenus dans les dossiers? (Sans compter par exemple que FC soit le dernier élément de la liste qui permettrait quelque chose comme ContainerClass*m_containers[FC+1] si je ne me trompe pas.)

89
fuenfundachtzig

Il n’ya pas vraiment de bonne façon de faire cela, vous voyez généralement un élément supplémentaire dans l’énum, ​​c’est-à-dire.

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

Alors vous pouvez faire:

int fuz[FOOBAR_NR_ITEMS];

Toujours pas très gentil cependant.

Mais bien sûr, vous réalisez que le nombre d’articles dans une énumération n’est pas sûr, par exemple.

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

le nombre d'éléments serait 4, mais les valeurs entières des valeurs enum seraient très éloignées de la plage d'index du tableau. L'utilisation de valeurs enum pour l'indexation de tableaux n'est pas sûre, vous devriez envisager d'autres options.

edit: à la demande, fait ressortir l’entrée spéciale davantage.

114
wich

Pour C++, il existe diverses techniques de type-safe enum disponibles, et certaines d'entre elles (telles que celle proposée mais non soumise Boost.Enum ) incluent le support pour obtenir la taille d'un enum.

L’approche la plus simple, qui fonctionne à la fois en C et en C++, consiste à adopter une convention consistant à déclarer une valeur ... MAX pour chacun de vos types d’énumération:

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

Edit : En ce qui concerne { FA, FB, FC, Folders_MAX = FC} contre {FA, FB, FC, Folders_MAX]: Je préfère définir la valeur ... MAX à la dernière valeur légale de l'énum pour plusieurs raisons:

  1. Le nom de la constante est techniquement plus précis (puisque Folders_MAX donne la valeur maximale enum possible).
  2. Personnellement, je me sens comme Folders_MAX = FC se démarque un peu plus des autres entrées (ce qui rend un peu plus difficile l'ajout accidentel de valeurs enum sans mettre à jour la valeur max, problème mentionné par Martin York).
  3. GCC inclut des avertissements utiles tels que "valeur d'énumération non incluse dans le commutateur" pour un code tel que celui-ci. Laisser Folders_MAX == FC + 1 interrompt ces avertissements, car vous vous retrouvez avec un tas de ... valeurs d'énumération MAX qui ne doivent jamais être incluses dans le commutateur.
commutateur 
 (dossier) 
 {
 cas FA: ...; 
 cas FB: ...; 
 // Oups, on a oublié FC ! 
} 
32
Josh Kelley

Qu'en est-il des traits, dans un style STL? Par exemple:

enum Foo
{
    Bar,
    Baz
};

écrire un

std::numeric_limits<enum Foo>::max()

spécialisation (éventuellement constexpr si vous utilisez c ++ 11). Ensuite, dans votre code de test, fournissez des assertions statiques pour maintenir les contraintes que std :: numeric_limits :: max () = last_item.

7
Wojciech Migda

Ajoutez une entrée, appelée Folders_MAX ou quelque chose de similaire, à la fin de votre enum et utilisez cette valeur lors de l'initialisation de vos tableaux.

ContainerClass* m_containers[Folders_MAX];
3
Kevin Doyon

J'aime utiliser des énumérations comme arguments de mes fonctions. C'est un moyen facile de fournir une liste fixe d '"options". Le problème avec la réponse la plus votée ici est qu’en utilisant cela, un client peut spécifier une "option invalide". En guise de spin-off, je vous recommande de faire essentiellement la même chose, mais utilisez une constante int en dehors de l'énum pour en définir le nombre.

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

Ce n'est pas agréable, mais c'est une solution propre si vous ne changez pas l'énum sans mettre à jour la constante.

2
BuvinJ

Je ne vois vraiment aucun moyen d'obtenir vraiment le nombre de valeurs dans une énumération en C++. Aucune des solutions précédentes ne fonctionne tant que vous ne définissez pas la valeur de vos énumérations si vous définissez vous-même la valeur que vous pourriez rencontrer dans des situations où vous créez des tableaux trop grands ou trop petits.

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

dans cet exemple, le résultat créerait un tableau de 3 éléments lorsque vous avez besoin d'un tableau de 5 éléments

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

dans cet exemple, le résultat créerait un tableau de 301 éléments lorsque vous avez besoin d'un tableau de 5 éléments

La meilleure façon de résoudre ce problème dans le cas général serait de parcourir vos énumérations, mais cela n’est pas encore dans la norme pour autant que je sache.

1
user4425844