Pregunta (¿Cómo puedo contar los artículos en una enumeración?


Me vino a la mente esta pregunta cuando tuve algo así como

enum Folders {FA, FB, FC};

y quería crear una matriz de contenedores para cada carpeta:

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

(Usar mapas es mucho más elegante de usar: std::map<Folders, ContainerClass*> m_containers;)

Pero para volver a mi pregunta original: ¿Qué pasa si no quiero codificar el tamaño de la matriz, hay alguna manera de averiguar cuántos elementos hay en Carpetas? (Sin depender de, por ejemplo, FC siendo el último elemento en la lista que permitiría algo así como ContainerClass*m_containers[FC+1] si no me equivoco.)


76
2018-01-20 15:37


origen


Respuestas:


Realmente no hay una buena manera de hacer esto, generalmente ves un ítem extra en la enumeración, es decir

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

Entonces puedes hacer:

int fuz[FOOBAR_NR_ITEMS];

Aún así no es muy agradable.

Pero, por supuesto, te das cuenta de que solo el número de elementos en una enumeración no es seguro, dado, p.

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

el número de elementos sería 4, pero los valores enteros de los valores enum estarían fuera del rango de índice de la matriz. El uso de valores enum para la indexación de matrices no es seguro, debe considerar otras opciones.

editar: según lo solicitado, hizo que la entrada especial sobresalga más.


98
2018-01-20 15:42



Para C ++, hay varios técnicas de enum seguro de tipo disponible, y algunos de ellos (como el propuesto pero nunca presentado) Boost.Enum) incluye soporte para obtener el tamaño de una enumeración.

El enfoque más simple, que funciona tanto en C como en C ++, es adoptar una convención de declarar un ... valor MAX para cada uno de sus tipos enum:

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

Editar: Respecto { FA, FB, FC, Folders_MAX = FC} versus {FA, FB, FC, Folders_MAX]: Prefiero establecer el ... valor MAX en el último valor legal de la enumeración por algunas razones:

  1. El nombre de la constante es técnicamente más preciso (desde Folders_MAX da el máximo valor de enum posible).
  2. Personalmente, siento que Folders_MAX = FC se destaca de otras entradas un poco más (lo que hace que sea un poco más difícil agregar accidentalmente valores enum sin actualizar el valor máximo, un problema al que hace referencia Martin York).
  3. GCC incluye advertencias útiles como "valor de enumeración no incluido en el interruptor" para el código, como el siguiente. Letting Folders_MAX == FC + 1 rompe esas advertencias, ya que terminas con un montón de ... MAX valores de enumeración que nunca deberían incluirse en el cambio.
cambiar (carpeta)
{
  caso FA: ...;
  caso FB: ...;
  // Vaya, ¡olvidé FC!
}

27
2018-01-20 15:48



¿Qué hay de los rasgos, de una manera STL? Por ejemplo:

enum Foo
{
    Bar,
    Baz
};

escribe un

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

especialización (posiblemente constexpr si usa c ++ 11). Luego, en su código de prueba proporcione cualquier aserciones estáticas para mantener las restricciones que std :: numeric_limits :: max () = last_item.


5
2017-12-23 13:23



Agregue una entrada, al final de su enumeración, llamada Folders_MAX o algo similar y use este valor al inicializar sus matrices.

ContainerClass* m_containers[Folders_MAX];

3
2018-01-20 15:42



Realmente no veo ninguna forma de llegar realmente al número de valores en una enumeración en C ++. Cualquiera de las soluciones antes mencionadas funciona siempre que no defina el valor de sus enumeraciones si define que valora que podría encontrarse con situaciones en las que cree matrices demasiado grandes o demasiado pequeñas

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

en este ejemplo, el resultado crearía una matriz de 3 elementos cuando necesita una matriz de 5 elementos

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

En este ejemplo, el resultado crearía una matriz de 301 elementos cuando necesite una matriz de 5 elementos.

La mejor manera de resolver este problema en el caso general sería iterar a través de sus enumeraciones, pero eso aún no está en el estándar, por lo que sé


1
2018-01-12 23:59



Me gusta usar enumeraciones como argumentos para mis funciones. Es un medio fácil de proporcionar una lista fija de "opciones". El problema con la respuesta más votado aquí es que al usar eso, un cliente puede especificar una "opción inválida". Como spin-off, recomiendo hacer esencialmente lo mismo, pero use una constante int fuera de la enumeración para definir el recuento de ellos.

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

No es agradable, pero es una solución limpia si no cambia la enumeración sin actualizar la constante.


1
2017-11-13 22:14