Supongamos que tenemos algunas enumeraciones con nombre:
enum MyEnum {
FOO,
BAR = 0x50
};
Lo que busqué en Google es un script (cualquier idioma) que escanea todos los encabezados de mi proyecto y genera un encabezado con una función por enumeración.
char* enum_to_string(MyEnum t);
Y una implementación con algo como esto:
char* enum_to_string(MyEnum t){
switch(t){
case FOO:
return "FOO";
case BAR:
return "BAR";
default:
return "INVALID ENUM";
}
}
El gotcha es realmente con enumeraciones typedefed y enumeraciones de estilo C sin nombre. ¿Alguien sabe algo para esto?
EDITAR: La solución no debe modificar mi fuente, excepto las funciones generadas. Las enumeraciones están en una API, por lo que usar las soluciones propuestas hasta ahora no es una opción.
Respuestas:
Es posible que desee consultar GCCXML .
Ejecutar GCCXML en su código de muestra produce:
Puede usar cualquier idioma que prefiera para extraer las etiquetas Enumeration y EnumValue y generar el código deseado.
fuente
Las macros X son la mejor solución. Ejemplo:
colores.def:
Sin embargo, generalmente prefiero el siguiente método, para que sea posible ajustar un poco la cadena.
fuente
#define X(a, b) #b
. Esto solo es necesario si la definición se ve asíX(Red, red)
, en lugar de la definición que se muestra en la respuesta,X(Red, "red")
@hydroo: Sin el archivo extra:
fuente
MetaSyntacticVariableNames[]
sea parte de una declaración de clase, haciendo un métodostatic const char* getNameByEnum(MetaSyntacticVariable e) { /*code to return the static string*/ }
Lo que tiendo a hacer es crear una matriz C con los nombres en el mismo orden y posición que los valores de enumeración.
p.ej.
entonces puede usar la matriz en lugares donde desea un valor legible para humanos, por ejemplo
Podrías experimentar un poco con el operador de encadenamiento (ver # en la referencia de tu preprocesador) que hará lo que quieras, en algunas circunstancias, por ejemplo:
imprimirá "rojo" en stdout. Desafortunadamente no funcionará para una variable (ya que obtendrá el nombre de la variable impreso)
fuente
Tengo una macro increíblemente simple de usar que hace esto de una manera completamente SECA. Involucra macros variables y algo de magia de análisis simple. Aquí va:
Para usar esto en su código, simplemente haga:
fuente
QT puede extraer eso de (gracias al compilador de metaobjetos):
Fuente
fuente
Esto se puede hacer en C ++ 11
fuente
Hoy reinventé esta rueda y pensé en compartirla.
Esta implementación no requiere ningún cambio en el código que define las constantes, que pueden ser enumeraciones
#define
o cualquier otra cosa que se transfiera a un número entero; en mi caso, tenía símbolos definidos en términos de otros símbolos. También funciona bien con valores dispersos. Incluso permite múltiples nombres para el mismo valor, devolviendo el primero siempre. El único inconveniente es que requiere que hagas una tabla de las constantes, que pueden quedar desactualizadas a medida que se agreguen nuevas, por ejemplo.Un ejemplo de cómo lo usarías:
La
IdToName
función se basa enstd::lower_bound
realizar búsquedas rápidas, lo que requiere que se ordene la tabla. Si las dos primeras entradas de la tabla están fuera de servicio, la función lo ordenará automáticamente.Editar: Un comentario me hizo pensar en otra forma de usar el mismo principio. Una macro simplifica la generación de una gran
switch
declaración.fuente
switch and case
ya que es simple y fácil de entender.Más discusión sobre este método
Trucos de directivas de preprocesador para recién llegados
fuente
Interesante ver la cantidad de formas. Aquí hay uno que usé hace mucho tiempo:
en el archivo myenummap.h:
en main.cpp
No es constante, pero es conveniente.
Aquí hay otra forma que usa las características de C ++ 11. Esto es constante, no hereda un contenedor STL y es un poco más ordenado:
fuente
Uso:
fuente
MyEnum x = MyEnum::TWO;
. He publicado mi edición de su clase para apoyar esto.La macro solución de Suma es agradable. Sin embargo, no es necesario tener dos macros diferentes. C ++ felizmente incluirá un encabezado dos veces. Solo deja de lado al guardia incluido.
Entonces tendrías un foobar.h definiendo solo
y lo incluirías así:
enumfactory.h hará 2
#include ENUMFACTORY_ARGUMENT
s. En la primera ronda, expande ENUM como el de SumaDECLARE_ENUM
; en la segunda ronda ENUM funciona comoDEFINE_ENUM
.También puede incluir enumfactory.h varias veces, siempre que pase diferentes # define para ENUMFACTORY_ARGUMENT
fuente
Tenga en cuenta que su función de conversión idealmente debería devolver un const char *.
Si puede permitirse poner sus enumeraciones en sus archivos de encabezado separados, tal vez podría hacer algo como esto con las macros (oh, esto será feo):
Donde enum_def.h tiene:
Y enum_conv.h tiene:
Y finalmente, colour.h tiene:
Y puede usar la función de conversión como:
Esto es feo, pero es la única forma (en el nivel de preprocesador) que le permite definir su enumeración solo en un solo lugar en su código. Por lo tanto, su código no es propenso a errores debido a modificaciones en la enumeración. Su definición de enumeración y la función de conversión siempre estarán sincronizadas. Sin embargo, repito, esto es feo :)
fuente
Otra respuesta: en algunos contextos, tiene sentido definir su enumeración en un formato sin código, como un archivo CSV, YAML o XML, y luego generar tanto el código de enumeración C ++ como el código de cadena a partir de la definición. Este enfoque puede o no ser práctico en su aplicación, pero es algo a tener en cuenta.
fuente
Esta es una modificación a la respuesta @ user3360260. Tiene las siguientes características nuevas
MyEnum fromString(const string&)
apoyoUso:
Aquí está el código
Tenga en cuenta que la conversión a String es una búsqueda rápida, mientras que la conversión de String es una búsqueda lineal lenta. Pero las cadenas son tan caras de todos modos (y el archivo asociado IO), no sentí la necesidad de optimizar o usar un bimap.
fuente
Aquí una solución de un archivo (basada en la elegante respuesta de @Marcin:
fuente
Hago esto con clases separadas de envoltura enum de lado a lado que se generan con macros. Hay varias ventajas:
La desventaja, por supuesto, es que necesito duplicar los valores de enumeración en las clases de formateador, y no tengo ningún script para generarlos. Aparte de eso, sin embargo, parece funcionar bastante bien.
Aquí hay un ejemplo de una enumeración de mi base de código, sin todo el código de marco que implementa las macros y las plantillas, pero puede hacerse una idea:
La idea es, en lugar de usar EHelpLocation, usar SEHelpLocation; todo funciona igual, pero obtienes una comprobación de rango y un método 'Format ()' en la variable enum. Si necesita formatear un valor independiente, puede usar CEnumFormatter_EHelpLocation :: FormatEnum (...).
Espero que esto sea útil. Me doy cuenta de que esto tampoco aborda la pregunta original sobre un guión para generar realmente la otra clase, pero espero que la estructura ayude a alguien a tratar de resolver el mismo problema o escribir dicho guión.
fuente
Es un software inédito, pero parece que BOOST_ENUM de Frank Laub podría cumplir con los requisitos. La parte que me gusta es que puedes definir una enumeración dentro del alcance de una clase que la mayoría de las enumeraciones basadas en Macro generalmente no te permiten hacer. Se encuentra en Boost Vault en: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=enum_rev4.6.zip&directory=& No ha visto ningún desarrollo desde 2006, así que no sepa qué tan bien se compila con los nuevos lanzamientos de Boost. Busque en libs / test un ejemplo de uso.
fuente
Esta fue mi solución con BOOST:
Para crear una enumeración, declare:
Para conversiones:
fuente
Quiero publicar esto en caso de que alguien lo encuentre útil.
En mi caso, simplemente necesito generar
ToString()
yFromString()
funciones para una sola enumeración de C ++ 11 desde un solo.hpp
archivo.Escribí un script de Python que analiza el archivo de encabezado que contiene los elementos de enumeración y genera las funciones en un nuevo
.cpp
archivo.Puede agregar este script en CMakeLists.txt con execute_process , o como un evento previo a la compilación en Visual Studio. El
.cpp
archivo se generará automáticamente, sin la necesidad de actualizarlo manualmente cada vez que se agregue un nuevo elemento de enumeración.generate_enum_strings.py
Ejemplo:
ErrorCode.hpp
correr
python generate_enum_strings.py ErrorCode.hpp
Resultado:
ErrorCode.cpp
fuente
Agregando aún más simplicidad de uso a la fantástica respuesta de Jasper Bekkers :
Configurar una vez:
Luego, para su uso:
fuente
Podrías usar una biblioteca de reflexión, como Ponder . Registra las enumeraciones y luego puede convertirlas de un lado a otro con la API.
fuente
Un problema con la respuesta 0 es que los valores binarios enum no necesariamente comienzan en 0 y no son necesariamente contiguos.
Cuando necesito esto, generalmente:
fuente
El siguiente script de Ruby intenta analizar los encabezados y acumula las fuentes necesarias junto con los encabezados originales.
El uso de expresiones regulares hace que este "analizador" sea bastante frágil, es posible que no pueda manejar sus encabezados específicos con gracia.
Supongamos que tiene un encabezado toto / ah, que contiene definiciones para las enumeraciones MyEnum y MyEnum2. El script construirá:
Las soluciones más robustas serían:
fuente
Esa es prácticamente la única forma en que se puede hacer (una matriz de cadenas también podría funcionar).
El problema es que, una vez que se compila un programa en C, el valor binario de la enumeración es todo lo que se usa, y el nombre desaparece.
fuente
Aquí hay un programa CLI que escribí para convertir fácilmente las enumeraciones en cadenas. Es fácil de usar, y toma alrededor de 5 segundos para hacerlo (incluido el tiempo para cd al directorio que contiene el programa, luego ejecutarlo, pasándole el archivo que contiene la enumeración).
Descargue aquí: http://www.mediafire.com/?nttignoozzz
Tema de discusión aquí: http://cboard.cprogramming.com/projects-job-recruitment/127488-free-program-im-sharing-convertenumtostrings.html
Ejecute el programa con el argumento "--help" para obtener una descripción de cómo usarlo.
fuente
No hace mucho tiempo, hice un truco para que las enumeraciones se mostraran correctamente en QComboBox y para tener la definición de enum y representaciones de cadenas como una sola declaración
Ahora
enumeration::enum_singleton<your_enum>::instance()
puede convertir las enumeraciones en cadenas. Si reemplazakv_storage_t
conboost::bimap
, también podrá realizar la conversión hacia atrás. Se introdujo la clase base común para el convertidor para almacenarlo en el objeto Qt, porque los objetos Qt no podían ser plantillasApariencia previa
fuente
Como variante, use lib simple> http://codeproject.com/Articles/42035/Enum-to-String-and-Vice-Versa-in-C
En el codigo
agregar líneas
Funciona bien, si los valores en enum no son duplicados .
Ejemplo de uso
y viceversa
fuente
Aquí hay un intento de obtener operadores de flujo << y >> en enumeración automáticamente con un comando de macro de una sola línea ...
Definiciones:
Uso:
Sin embargo, no estoy seguro de las limitaciones de este esquema ... ¡los comentarios son bienvenidos!
fuente
fuente