(Comment) puis-je compter les objects dans un enum?

Cette question m’est venue à l’esprit quand 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. 

(L’utilisation de cartes est beaucoup plus élégante: std::map m_containers; )

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

    Il n’y a pas vraiment un bon moyen de le faire, généralement vous voyez un élément supplémentaire dans l’énumération, c.-à-d.

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

    Alors, vous pouvez faire:

     int fuz[FOOBAR_NR_ITEMS]; 

    Toujours pas très bien cependant.

    Mais bien sûr, vous réalisez que le nombre d’éléments dans un enum 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 d’énumération seraient bien en dehors de la plage d’index du tableau. L’utilisation des valeurs enum pour l’indexation de tableau n’est pas sûre, vous devez envisager d’autres options.

    edit: comme demandé, fait en sorte que l’entrée spéciale ressorte plus.

    Pour C ++, il existe différentes techniques d’énumération de type sécurisé , et certaines d’entre elles (telles que Boost.Enum, proposées mais jamais soumises) incluent la prise en charge de la taille d’un enum.

    L’approche la plus simple, qui fonctionne aussi bien en C qu’en C ++, est d’adopter une convention de déclaration d’une valeur … MAX pour chacun de vos types enum:

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

    Edit : Concernant { FA, FB, FC, Folders_MAX = FC} contre {FA, FB, FC, Folders_MAX] : Je préfère définir la valeur … MAX sur la dernière valeur légale de l’énumération pour plusieurs raisons:

    1. Le nom de la constante est techniquement plus précis (puisque Folders_MAX donne la valeur enum maximale possible).
    2. Personnellement, je pense que Folders_MAX = FC se démarque un peu plus des autres entrées (ce qui rend un peu plus difficile d’append accidentellement des valeurs sans mettre à jour la valeur maximale, un problème auquel Martin York a fait référence).
    3. GCC inclut des avertissements utiles comme “valeur d’énumération non incluse dans le commutateur” pour du code tel que le suivant. Laisser Folders_MAX == FC + 1 rompt ces avertissements, puisque vous vous retrouvez avec un tas de … valeurs d’énumération MAX qui ne doivent jamais être incluses dans switch.
     commutateur (dossier) 
     {
       case FA: ...;
       case FB: ...;
       // Oups, j'ai oublié FC!
     }
    

    Qu’en est-il des traits, en mode STL? Par exemple:

     enum Foo { Bar, Baz }; 

    écrire un

     std::numeric_limits::max() 

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

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

     ContainerClass* m_containers[Folders_MAX]; 

    Je ne vois vraiment pas comment atteindre le nombre de valeurs dans une énumération en C ++. N’importe laquelle de la solution mentionnée ci-dessus fonctionne tant que vous ne définissez pas la valeur de vos énumérations si vous définissez la valeur que vous pourriez rencontrer dans des situations où vous créez des baies trop grandes ou trop petites.

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

    dans ce cas d’exemples, 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 ce cas d’exemples, 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 le cas pour autant que je sache.

    J’aime utiliser des énumérations comme arguments pour mes fonctions. C’est un moyen facile de fournir une liste fixe “d’options”. Le problème avec la réponse votée ici est que, en utilisant cela, un client peut spécifier une “option invalide”. Comme spin-off, je recommande de faire essentiellement la même chose, mais utilisez un int constant en dehors de l’enum 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 modifiez pas l’énumération sans mettre à jour la constante.