Los elementos vinculados tienen algunas respuestas interesantes.
Tony
¡Estas respuestas no parecen cubrir el problema que intpuede no ser lo suficientemente grande! ( [C++03: 7.2/5])
Carreras de ligereza en órbita
Curiosamente, puede definir operator++en enumeraciones; Sin embargo, para que pueda hacer for(Enum_E e = (Enum_E)0; e < ENUM_COUNT; e++). Tenga en cuenta que debe enviar 0a Enum_Eporque C ++ prohíbe los operadores de asignación en las enumeraciones.
weberc2
Si hubiera un operador de tiempo de compilación, similar a la forma en que funciona sizeof, que podría emitir un literal std :: initializer_list compuesto por los valores de la enumeración, tendríamos una solución y no implicaría ninguna sobrecarga de tiempo de ejecución.
Tenga en cuenta que Lastla iteración debe omitir la enumeración . Al utilizar esta Lastenumeración "falsa" , no tiene que actualizar su condición de terminación en el bucle for hasta la última enumeración "real" cada vez que desee agregar una enumeración nueva. Si desea agregar más enumeraciones más tarde, solo agréguelas antes de Last. El bucle en este ejemplo seguirá funcionando.
Por supuesto, esto se rompe si se especifican los valores de enumeración:
enumFoo{One=1,Two=9,Three=4,Last};
Esto ilustra que una enumeración no está destinada a iterar. La forma típica de lidiar con una enumeración es usarla en una declaración de cambio.
Si realmente quieres enumerar, rellena los valores de enumeración en un vector e itera sobre eso. Esto también se ocupará adecuadamente de los valores de enumeración especificados.
Tenga en cuenta que, en la primera parte del ejemplo, si desea usar 'i' como una enumeración de Foo y no un int, deberá emitir estática como: static_cast <Foo> (i)
Clayton
55
También estás saltando Last in the loop. Debería ser <= Último
Tony
20
@Tony Last está destinado a ser omitido. Si desea agregar más enumeraciones más tarde, agréguelas antes de Última ... el bucle en el primer ejemplo seguirá funcionando. Al utilizar una última enumeración "falsa", no tiene que actualizar su condición de terminación en el bucle for a la última enumeración "real" cada vez que desee agregar una nueva enumeración.
timidpueo
Excepto que ahora ha asignado memoria cuando una enumeración, siempre que esté indexada a cero y sea estrictamente continua, puede hacer esa tarea sin asignar memoria.
Nube
1
Tenga en cuenta que para que esta definición de enumeración sea segura para las actualizaciones, se debe definir un valor UNKNOWN = 0. Además, sugeriría simplemente descartar el defaultcaso al cambiar los valores de enumeración, ya que podría ocultar casos en los que se olvidó el manejo de valores hasta el tiempo de ejecución. En cambio, uno debe codificar todos los valores y usar el UNKNOWNcampo para detectar incompatibilidades.
Benjamin Bannier
53
#include<iostream>#include<algorithm>namespaceMyEnum{enumType{
a =100,
b =220,
c =-1};staticconstTypeAll[]={ a, b, c };}void fun(constMyEnum::Type e ){
std::cout << e << std::endl;}int main(){// allfor(constauto e :MyEnum::All)
fun( e );// somefor(constauto e :{MyEnum::a,MyEnum::b })
fun( e );// all
std::for_each( std::begin(MyEnum::All), std::end(MyEnum::All), fun );return0;}
¡Gracias! Tenga en cuenta que si está cruzando archivos / clases y si la compatibilidad con MS le está dando problemas con las constantes no enteras declaradas por el encabezado, ayuda en mi compilador colocar explícitamente el tamaño en el tipo en el encabezado: static const Type All[3];y luego puedo para inicializar en la fuente: const MyEnum::Type MyEnum::All[3] = { a, b, c }; Antes de hacer eso, recibía Error in range-based for...errores desagradables (porque la matriz tenía un tamaño desconocido). Lo descubrí gracias a una respuesta relacionada
sabio
1
La versión de matriz es muy amigable de copiar y pegar. La respuesta más satisfactoria además, "NO" o "solo para secuencial". Probablemente macro amigable incluso.
Paulo Neves
1
Esta podría ser una buena solución para enumeraciones con una pequeña cantidad de elementos, pero para enumeraciones con una gran cantidad de elementos no debe ajustarse bien.
kato2
20
Si su enumeración comienza con 0 y el incremento es siempre 1.
Con c ++ 11, en realidad hay una alternativa: escribir un iterador personalizado con plantilla simple.
supongamos que tu enumeración es
enumclass foo {
one,
two,
three
};
Este código genérico hará el truco, de manera bastante eficiente: colóquelo en un encabezado genérico, le servirá para cualquier enumeración que necesite repetir:
#include<type_traits>template<typename C, C beginVal, C endVal>classIterator{typedeftypename std::underlying_type<C>::type val_t;int val;public:Iterator(const C & f): val(static_cast<val_t>(f)){}Iterator(): val(static_cast<val_t>(beginVal)){}Iteratoroperator++(){++val;return*this;}
C operator*(){returnstatic_cast<C>(val);}Iterator begin(){return*this;}//default ctor is goodIterator end(){staticconstIterator endIter=++Iterator(endVal);// cache itreturn endIter;}booloperator!=(constIterator& i){return val != i.val;}};
for(foo i : fooIterator()){//notice the parentheses!
do_stuff(i);}
La suposición de que no tienes huecos en tu enumeración sigue siendo cierta; no se supone el número de bits realmente necesarios para almacenar el valor de enumeración (gracias a std :: subyacente_tipo)
No sé por qué esto fue rechazado. Es una solución razonable.
Paul Brannan
11
Supongo que fue porque las entradas deben mantenerse en dos lugares.
Ant
¿C ++ permite la for (NodePosition pos : NodePositionVector)sintaxis? Hasta donde sé, esta es la sintaxis de Java, y necesitará iteradores en C ++ para hacer algo equivalente.
thegreatjedi
3
@thegreatjedi Desde C ++ 11 puedes, incluso más simple: for (auto pos: NodePositionVector) {..}
Enzojz
@thegreatjedi Hubiera sido más rápido buscar, o incluso compilar un programa de prueba, que hacer esa pregunta. Pero sí, desde C ++ 11 es una sintaxis C ++ perfectamente válida, que el compilador traduce al código equivalente (y mucho más detallado / menos abstracto), generalmente a través de iteradores; ver cppreference . Y, como dijo Enzojz, C ++ 11 también agregó auto, por lo que no tiene que declarar el tipo de elementos explícitamente, a menos que (A) necesite usar un operador de conversión o (B) no le guste autopor alguna razón . La mayoría de los forusuarios de autorango usan AFAICT
underscore_d
9
A menudo lo hago así
enumEMyEnum{
E_First,
E_Orange = E_First,
E_Green,
E_White,
E_Blue,
E_Last
}for(EMyEnum i = E_First; i < E_Last; i =EMyEnum(i +1)){}
o si no es sucesivo, pero con un paso regular (por ejemplo, banderas de bits)
Usar enumeraciones para crear máscaras de bits. por ejemplo, combine varias opciones en una sola variable, luego use FOR para probar cada opción. Se arregló mi publicación con un mejor ejemplo.
Niki
¡Todavía no puedo usarlo (y tu publicación aún muestra el viejo ejemplo)! Usar enum como máscaras de bits es realmente útil, ¡pero no pudo conectar los puntos! ¿podría explicar un poco más su ejemplo en los detalles? También puede poner el código adicional.
Anu
@anu Lo siento, no vi tu comentario. Se agregó la clase Frog como ejemplo de máscara de bits
Niki
8
No puedes con una enumeración. Quizás una enumeración no sea la más adecuada para su situación.
Una convención común es nombrar el último valor de enumeración como MAX y usarlo para controlar un bucle usando un int.
Aquí hay varios ejemplos que demuestran lo contrario. En tu propia afirmación te estás contradiciendo (segunda línea).
Niki
6
Algo que no se ha cubierto en las otras respuestas = si está usando enumeraciones de C ++ 11 fuertemente tipadas, no puede usarlas ++ni + inten ellas. En ese caso, se requiere un poco de una solución más desordenada:
enumCount{ zero, one, two, three };
for_range (Count, c, zero, three){
cout <<"forward: "<< c << endl;}
Se puede usar para iterar hacia atrás y hacia adelante a través de enteros, enteros y caracteres sin signo:
for_range (unsigned, i,10,0){
cout <<"backwards i: "<< i << endl;}
for_range (char, c,'z','a'){
cout << c << endl;}
A pesar de su definición incómoda, está optimizado muy bien. Miré al desensamblador en VC ++. El código es extremadamente eficiente. No se desanime, sino las tres declaraciones for: ¡el compilador producirá solo un ciclo después de la optimización! Incluso puede definir bucles cerrados:
unsigned p[4][5];
for_range (Count, i, zero,three)
for_range(unsignedint, j,4,0){
p[i][j]=static_cast<unsigned>(i)+j;}
Obviamente no puede iterar a través de tipos enumerados con huecos.
La sobrecarga del incremento / decremento requiere tomar una decisión sobre qué hacer cuando hay un desbordamiento
Eponymous
3
Asumir que enum está numerado secuencialmente es propenso a errores. Además, es posible que desee iterar solo sobre los enumeradores seleccionados. Si ese subconjunto es pequeño, recorrerlo explícitamente podría ser una opción elegante:
enumItem{Man,Wolf,Goat,Cabbage};// or enum classfor(auto item :{Wolf,Goat,Cabbage}){// or Item::Wolf, ...// ...}
Esta es una buena opción, creo. ¿Debe ser parte de una nueva especificación de C ++ que estaba usando cuando hice la pregunta que supongo?
Adam
Si. Se itera sobre un std :: initializer_list <Item>. enlace .
marski
2
Si no le gusta contaminar su enumeración con un elemento COUNT final (porque tal vez si también utiliza la enumeración en un conmutador, entonces el compilador le avisará de la falta de un caso COUNT :), puede hacer esto:
enumColour{Red,Green,Blue};constColourLastColour=Blue;Colour co(0);while(true){// do stuff with co// ...if(co ==LastColour)break;
co =Colour(co+1);}
Aquí hay otra solución que solo funciona para enumeraciones contiguas. Da la iteración esperada, excepto por la fealdad en el incremento, que es donde pertenece, ya que eso es lo que está roto en C ++.
enumBar{One=1,Two,Three,End_Bar// Marker for end of enum; };for(Bar foo =One; foo <End_Bar; foo =Bar(foo +1)){// ...}
El incremento se puede acortar a foo = Bar(foo + 1).
HolyBlackCat
Gracias, HolyBlackCat, ¡he incorporado tu excelente sugerencia! También noto que Riot tiene más o menos esta misma solución, pero conforme con un tipeo fuerte (y, por lo tanto, más detallado).
Ethan Bradford el
2
enumclass A {
a0=0, a3=3, a4=4};constexpr std::array<A,3> ALL_A {A::a0, A::a3, A::a4};// constexpr is important herefor(A a: ALL_A){if(a==A::a0 || a==A::a4) std::cout <<static_cast<int>(a);}
UNA constexpr std::array puede iterar incluso enumeraciones no secuenciales sin que la matriz sea instanciada por el compilador. Esto depende de cosas como la heurística de optimización del compilador y de si toma la dirección de la matriz.
En mis experimentos, descubrí que g++9.1 -O3optimizará la matriz anterior si hay 2 valores no secuenciales o bastantes valores secuenciales (probé hasta 6). Pero solo hace esto si tiene una ifdeclaración. (Probé una declaración que comparó un valor entero mayor que todos los elementos en una matriz secuencial y alineó la iteración a pesar de que no se excluyó ninguno, pero cuando omití la declaración if, los valores se guardaron en la memoria). valores de una enumeración no secuencial en [un caso | https://godbolt.org/z/XuGtoc] . Sospecho que este comportamiento extraño se debe a la profunda heurística que tiene que ver con los cachés y la predicción de ramas.
Me gusta la semántica de bucle for de rango simple y creo que evolucionará aún más, por eso me gusta esta solución.
rtischer8277
2
En el libro de lenguaje de programación C ++ de Bjarne Stroustrup, puede leer que está proponiendo sobrecargar el operator++para su específico enum. enumson tipos definidos por el usuario y el operador de sobrecarga existe en el idioma para estas situaciones específicas.
Podrás codificar lo siguiente:
#include<iostream>enumclassColors{red, green, blue};Colors&operator++(Colors&c,int){switch(c){caseColors::red:return c=Colors::green;caseColors::green:return c=Colors::blue;caseColors::blue:return c=Colors::red;// managing overflowdefault:throw std::exception();// or do anything else to manage the error...}}int main(){Colors c =Colors::red;// casting in int just for convenience of output.
std::cout <<(int)c++<< std::endl;
std::cout <<(int)c++<< std::endl;
std::cout <<(int)c++<< std::endl;
std::cout <<(int)c++<< std::endl;
std::cout <<(int)c++<< std::endl;return0;}
Mente que estoy usando enum class. El código funciona bien con enumtambién. Pero prefiero enum classya que son de tipo fuerte y pueden evitar que cometamos errores en el momento de la compilación.
Se emitió un voto negativo en esta publicación. ¿Alguna razón por la que no respondería a la pregunta?
LAL
La razón es probablemente porque esta es una solución terrible desde el punto de vista arquitectónico: te obliga a escribir una lógica global destinada a un componente específico (tu enumeración), además, si tu enumeración cambia por cualquier razón, te ves obligado a editar tu + + operador también, como enfoque no es sostenible para ningún proyecto de mediana-gran escala, no es una sorpresa que provenga de una recomendación de Bjarne Stroustrup, en la época en que la arquitectura del software era como ciencia ficción
Manjia
La pregunta original es acerca de tener un operador para un enum. No era una pregunta arquitectónica. No creo que en 2013 C ++ fuera una ciencia ficción.
LAL
1
Para compiladores de MS:
#define inc_enum(i)((decltype(i))((int)i +1))enum enumtype { one, two, three, count};for(enumtype i = one; i < count; i = inc_enum(i)){
dostuff(i);}
Nota: este es mucho menos código que la respuesta del iterador personalizado simple con plantilla.
Puede hacer que esto funcione con GCC usando en typeoflugar de decltype, pero no tengo ese compilador a mano en este momento para asegurarme de que se compila.
Esto se escribió ~ 5 años después de decltypeconvertirse en C ++ estándar, por lo que no debe recomendar el anticuado typeofdel antiguo CCG. GCC vagamente reciente se maneja decltypemuy bien. Hay otros problemas: se desalientan los modelos de estilo C y las macros son peores. Las características adecuadas de C ++ pueden proporcionar la misma funcionalidad genérica. Esto sería mejor volver a escribir a utilizar static_casty una función de plantilla: template <typename T> auto inc_enum(T const t) { return static_cast<T>(static cast<int>(t) + 1); }. Y los moldes no son necesarios para no enum class. Alternativamente, los operadores pueden sobrecargarse por enumtipo (TIL)
underscore_d
1
typedefenum{
first =2,
second =6,
third =17}MyEnum;staticconstint enumItems[]={
first,
second,
third
}staticconstintEnumLength=sizeof(enumItems)/sizeof(int);for(int i =0; i <EnumLength; i++){//Do something with enumItems[i]}
Esta solución va a crear una variables estáticas innecesariamente en la memoria mientras que el objetivo de enumeración es sólo para crear una 'máscara' a las constantes inline
TheArquitect
A menos que haya cambiado aconstexpr static const int enumItems[]
Mohammad Kanan
0
C ++ no tiene introspección, por lo que no puede determinar este tipo de cosas en tiempo de ejecución.
¿Podría explicarme por qué sería necesaria la "introspección" para iterar sobre una enumeración?
Jonathan Mee el
¿Quizás el término es Reflexión ?
kͩeͣmͮpͥ ͩ
2
Estoy tratando de decir 2 cosas: 1) Por muchas otras respuestas, C ++ puede lograr esto, por lo que si va a decir que no puede, se requiere un enlace o una aclaración adicional. 2) En su forma actual, este es, en el mejor de los casos, un comentario, ciertamente no una respuesta.
Jonathan Mee
Rechace mi respuesta entonces - Creo que lo ha justificado más que bien
kͩeͣmͮpͥ ͩ
1
Volveré a escribir 2 comentarios: 1) No voté en contra porque encuentro que recibir un voto en contra desmotiva la participación en el sitio, encuentro que es contraproducente 2) Todavía no entiendo lo que estás tratando de decir, pero parece que entiendes algo que no entiendo, en cuyo caso preferiría que elabores en lugar de eliminar una respuesta rechazada.
Jonathan Mee
0
Si supiera que los valores de enumeración son secuenciales, por ejemplo, Qt: Clave enumeración, podría:
Simplemente haga una matriz de entradas y repita sobre la matriz, pero haga que el último elemento diga -1 y úselo para la condición de salida.
Si enum es:
enumMyEnumType{Hay=12,Grass=42,Beer=39};
luego crea una matriz:
intArray[]={Hay,Grass,Beer,-1};for(int h =0;Array[h]!=-1; h++){
doStuff((MyEnumType)Array[h]);}
Esto no se descompone, independientemente de las entradas en la representación, siempre que la comprobación -1 no choque con uno de los elementos, por supuesto.
int
puede no ser lo suficientemente grande! ([C++03: 7.2/5]
)operator++
en enumeraciones; Sin embargo, para que pueda hacerfor(Enum_E e = (Enum_E)0; e < ENUM_COUNT; e++)
. Tenga en cuenta que debe enviar0
aEnum_E
porque C ++ prohíbe los operadores de asignación en las enumeraciones.Respuestas:
La forma típica es la siguiente:
Tenga en cuenta que
Last
la iteración debe omitir la enumeración . Al utilizar estaLast
enumeración "falsa" , no tiene que actualizar su condición de terminación en el bucle for hasta la última enumeración "real" cada vez que desee agregar una enumeración nueva. Si desea agregar más enumeraciones más tarde, solo agréguelas antes de Last. El bucle en este ejemplo seguirá funcionando.Por supuesto, esto se rompe si se especifican los valores de enumeración:
Esto ilustra que una enumeración no está destinada a iterar. La forma típica de lidiar con una enumeración es usarla en una declaración de cambio.
Si realmente quieres enumerar, rellena los valores de enumeración en un vector e itera sobre eso. Esto también se ocupará adecuadamente de los valores de enumeración especificados.
fuente
UNKNOWN = 0
. Además, sugeriría simplemente descartar eldefault
caso al cambiar los valores de enumeración, ya que podría ocultar casos en los que se olvidó el manejo de valores hasta el tiempo de ejecución. En cambio, uno debe codificar todos los valores y usar elUNKNOWN
campo para detectar incompatibilidades.fuente
static const Type All[3];
y luego puedo para inicializar en la fuente:const MyEnum::Type MyEnum::All[3] = { a, b, c };
Antes de hacer eso, recibíaError in range-based for...
errores desagradables (porque la matriz tenía un tamaño desconocido). Lo descubrí gracias a una respuesta relacionadaSi su enumeración comienza con 0 y el incremento es siempre 1.
Si no, supongo que el único motivo es crear algo así como
agregue los elementos y use iteradores normales ...
fuente
Con c ++ 11, en realidad hay una alternativa: escribir un iterador personalizado con plantilla simple.
supongamos que tu enumeración es
Este código genérico hará el truco, de manera bastante eficiente: colóquelo en un encabezado genérico, le servirá para cualquier enumeración que necesite repetir:
Tendrás que especializarlo
Y luego puedes iterar usando range-for
La suposición de que no tienes huecos en tu enumeración sigue siendo cierta; no se supone el número de bits realmente necesarios para almacenar el valor de enumeración (gracias a std :: subyacente_tipo)
fuente
std::vector
no es genérico porquestd::vector<foo>
está vinculado afoo
.typedef Iterator<color, color::green, color::red> colorIterator;
Asegúrese de comprender cómo funcionan las instancias de plantilla.foo operator*() { ...
debería serloC operator*() { ...
.estas soluciones son demasiado complicadas, me gusta eso:
fuente
for (NodePosition pos : NodePositionVector)
sintaxis? Hasta donde sé, esta es la sintaxis de Java, y necesitará iteradores en C ++ para hacer algo equivalente.auto
, por lo que no tiene que declarar el tipo de elementos explícitamente, a menos que (A) necesite usar un operador de conversión o (B) no le gusteauto
por alguna razón . La mayoría de losfor
usuarios deauto
rango usan AFAICTA menudo lo hago así
o si no es sucesivo, pero con un paso regular (por ejemplo, banderas de bits)
fuente
No puedes con una enumeración. Quizás una enumeración no sea la más adecuada para su situación.
Una convención común es nombrar el último valor de enumeración como MAX y usarlo para controlar un bucle usando un int.
fuente
Algo que no se ha cubierto en las otras respuestas = si está usando enumeraciones de C ++ 11 fuertemente tipadas, no puede usarlas
++
ni+ int
en ellas. En ese caso, se requiere un poco de una solución más desordenada:fuente
Puede intentar definir la siguiente macro:
Ahora puedes usarlo:
Se puede usar para iterar hacia atrás y hacia adelante a través de enteros, enteros y caracteres sin signo:
A pesar de su definición incómoda, está optimizado muy bien. Miré al desensamblador en VC ++. El código es extremadamente eficiente. No se desanime, sino las tres declaraciones for: ¡el compilador producirá solo un ciclo después de la optimización! Incluso puede definir bucles cerrados:
Obviamente no puede iterar a través de tipos enumerados con huecos.
fuente
_A1
no es un nombre permitido, es un guión bajo destacado con la siguiente letra mayúscula.También puede sobrecargar los operadores de incremento / decremento para su tipo enumerado.
fuente
Asumir que enum está numerado secuencialmente es propenso a errores. Además, es posible que desee iterar solo sobre los enumeradores seleccionados. Si ese subconjunto es pequeño, recorrerlo explícitamente podría ser una opción elegante:
fuente
Si no le gusta contaminar su enumeración con un elemento COUNT final (porque tal vez si también utiliza la enumeración en un conmutador, entonces el compilador le avisará de la falta de un caso COUNT :), puede hacer esto:
fuente
Aquí hay otra solución que solo funciona para enumeraciones contiguas. Da la iteración esperada, excepto por la fealdad en el incremento, que es donde pertenece, ya que eso es lo que está roto en C ++.
fuente
foo = Bar(foo + 1)
.UNA
constexpr std::array
puede iterar incluso enumeraciones no secuenciales sin que la matriz sea instanciada por el compilador. Esto depende de cosas como la heurística de optimización del compilador y de si toma la dirección de la matriz.En mis experimentos, descubrí que
g++
9.1-O3
optimizará la matriz anterior si hay 2 valores no secuenciales o bastantes valores secuenciales (probé hasta 6). Pero solo hace esto si tiene unaif
declaración. (Probé una declaración que comparó un valor entero mayor que todos los elementos en una matriz secuencial y alineó la iteración a pesar de que no se excluyó ninguno, pero cuando omití la declaración if, los valores se guardaron en la memoria). valores de una enumeración no secuencial en [un caso | https://godbolt.org/z/XuGtoc] . Sospecho que este comportamiento extraño se debe a la profunda heurística que tiene que ver con los cachés y la predicción de ramas.Aquí hay un enlace a una iteración de prueba simple en godbolt que demuestra que la matriz no siempre se instancia.
El precio de esta técnica es escribir los elementos de enumeración dos veces y mantener las dos listas sincronizadas.
fuente
En el libro de lenguaje de programación C ++ de Bjarne Stroustrup, puede leer que está proponiendo sobrecargar el
operator++
para su específicoenum
.enum
son tipos definidos por el usuario y el operador de sobrecarga existe en el idioma para estas situaciones específicas.Podrás codificar lo siguiente:
código de prueba: http://cpp.sh/357gb
Mente que estoy usando
enum class
. El código funciona bien conenum
también. Pero prefieroenum class
ya que son de tipo fuerte y pueden evitar que cometamos errores en el momento de la compilación.fuente
enum
. No era una pregunta arquitectónica. No creo que en 2013 C ++ fuera una ciencia ficción.Para compiladores de MS:
Nota: este es mucho menos código que la respuesta del iterador personalizado simple con plantilla.
Puede hacer que esto funcione con GCC usando en
typeof
lugar dedecltype
, pero no tengo ese compilador a mano en este momento para asegurarme de que se compila.fuente
decltype
convertirse en C ++ estándar, por lo que no debe recomendar el anticuadotypeof
del antiguo CCG. GCC vagamente reciente se manejadecltype
muy bien. Hay otros problemas: se desalientan los modelos de estilo C y las macros son peores. Las características adecuadas de C ++ pueden proporcionar la misma funcionalidad genérica. Esto sería mejor volver a escribir a utilizarstatic_cast
y una función de plantilla:template <typename T> auto inc_enum(T const t) { return static_cast<T>(static cast<int>(t) + 1); }
. Y los moldes no son necesarios para noenum class
. Alternativamente, los operadores pueden sobrecargarse porenum
tipo (TIL)fuente
constexpr static const int enumItems[]
C ++ no tiene introspección, por lo que no puede determinar este tipo de cosas en tiempo de ejecución.
fuente
Si supiera que los valores de enumeración son secuenciales, por ejemplo, Qt: Clave enumeración, podría:
Funciona como se esperaba.
fuente
Simplemente haga una matriz de entradas y repita sobre la matriz, pero haga que el último elemento diga -1 y úselo para la condición de salida.
Si enum es:
luego crea una matriz:
Esto no se descompone, independientemente de las entradas en la representación, siempre que la comprobación -1 no choque con uno de los elementos, por supuesto.
fuente