Supposons que nous ayons des énumérations nommées:
enum MyEnum {
FOO,
BAR = 0x50
};
Ce que j'ai recherché sur Google, c'est un script (n'importe quelle langue) qui analyse tous les en-têtes de mon projet et génère un en-tête avec une fonction par énumération.
char* enum_to_string(MyEnum t);
Et une implémentation avec quelque chose comme ça:
char* enum_to_string(MyEnum t){
switch(t){
case FOO:
return "FOO";
case BAR:
return "BAR";
default:
return "INVALID ENUM";
}
}
Le gotcha est vraiment avec des énumérations typedefed et des énumérations de style C sans nom. Quelqu'un sait-il quelque chose à ce sujet?
EDIT: La solution ne doit pas modifier ma source, sauf pour les fonctions générées. Les énumérations sont dans une API, donc utiliser les solutions proposées jusqu'à présent n'est tout simplement pas une option.
Réponses:
Vous voudrez peut-être consulter GCCXML .
L'exécution de GCCXML sur votre exemple de code produit:
Vous pouvez utiliser n'importe quel langage que vous préférez pour extraire les balises Enumeration et EnumValue et générer le code souhaité.
la source
Les macros X sont la meilleure solution. Exemple:
colours.def:
Cependant, je préfère généralement la méthode suivante, afin qu'il soit possible de modifier un peu la chaîne.
la source
#define X(a, b) #b
. Cela n'est nécessaire que si la définition ressemble à ceciX(Red, red)
, plutôt que la définition montrée dans la réponse,X(Red, "red")
@hydroo: Sans le fichier supplémentaire:
la source
MetaSyntacticVariableNames[]
faire partie d'une déclaration de classe, en créant une méthodestatic const char* getNameByEnum(MetaSyntacticVariable e) { /*code to return the static string*/ }
Ce que j'ai tendance à faire est de créer un tableau C avec les noms dans le même ordre et la même position que les valeurs d'énumération.
par exemple.
alors vous pouvez utiliser le tableau aux endroits où vous voulez une valeur lisible par l'homme, par exemple
Vous pouvez expérimenter un peu avec l'opérateur de stringizing (voir # dans votre référence de préprocesseur) qui fera ce que vous voulez, dans certaines circonstances - par exemple:
affichera "rouge" sur stdout. Malheureusement, cela ne fonctionnera pas pour une variable (car vous obtiendrez le nom de la variable imprimé)
la source
J'ai une macro incroyablement simple à utiliser qui le fait de manière complètement sèche. Cela implique des macros variadiques et une simple magie d'analyse. Voici:
Pour utiliser ceci dans votre code, faites simplement:
la source
QT est capable d'extraire celui de (grâce au compilateur de méta-objets):
La source
la source
Cela peut être fait en C ++ 11
la source
Je viens de réinventer cette roue aujourd'hui et j'ai pensé la partager.
Cette mise en œuvre ne pas besoin de modifier le code qui définit les constantes qui peuvent être énumérations ou
#define
s ou toute autre chose qui échoit un entier - dans mon cas , j'avais des symboles définis en termes d'autres symboles. Cela fonctionne également bien avec des valeurs clairsemées. Il autorise même plusieurs noms pour la même valeur, renvoyant toujours le premier. Le seul inconvénient est que cela vous oblige à créer un tableau des constantes, qui pourraient devenir obsolètes lorsque de nouvelles sont ajoutées par exemple.Un exemple de la façon dont vous l'utiliseriez:
La
IdToName
fonction s'appuie surstd::lower_bound
des recherches rapides, ce qui nécessite le tri de la table. Si les deux premières entrées du tableau sont dans le désordre, la fonction le triera automatiquement.Edit: Un commentaire m'a fait penser à une autre façon d'utiliser le même principe. Une macro simplifie la génération d'une grande
switch
instruction.la source
switch and case
car c'est simple et facile à comprendre.Discussion supplémentaire sur cette méthode
Astuces de directive de préprocesseur pour les nouveaux arrivants
la source
Intéressant de voir le nombre de façons. en voici un que j'ai utilisé il y a longtemps:
dans le fichier myenummap.h:
dans main.cpp
Ce n'est pas un const, mais c'est pratique.
Voici une autre façon d'utiliser les fonctionnalités de C ++ 11. Ceci est const, n'hérite pas d'un conteneur STL et est un peu plus ordonné:
la source
Usage:
la source
MyEnum x = MyEnum::TWO;
. J'ai publié ma modification de votre classe pour soutenir cela.La solution macro de Suma est bien. Cependant, vous n'avez pas besoin d'avoir deux macros différentes. C ++ inclura heureusement un en-tête deux fois. Laissez de côté la garde d'inclusion.
Vous auriez donc un foobar.h définissant juste
et vous l'incluez comme ceci:
enumfactory.h fera 2
#include ENUMFACTORY_ARGUMENT
s. Au premier tour, il étend ENUM comme celui de SumaDECLARE_ENUM
; au deuxième tour, ENUM fonctionne commeDEFINE_ENUM
.Vous pouvez également inclure enumfactory.h plusieurs fois, à condition de transmettre différents # define pour ENUMFACTORY_ARGUMENT
la source
Notez que votre fonction de conversion devrait idéalement renvoyer un const char *.
Si vous pouvez vous permettre de mettre vos énumérations dans leurs fichiers d'en-tête séparés, vous pouvez peut-être faire quelque chose comme ça avec des macros (oh, ce sera moche):
Où enum_def.h a:
Et enum_conv.h a:
Et enfin, colour.h a:
Et vous pouvez utiliser la fonction de conversion comme:
C'est moche, mais c'est le seul moyen (au niveau du préprocesseur) qui vous permet de définir votre énumération à un seul endroit de votre code. Votre code n'est donc pas sujet à des erreurs dues à des modifications de l'énumération. Votre définition d'énumération et la fonction de conversion seront toujours synchronisées. Cependant, je le répète, c'est moche :)
la source
Une autre réponse: dans certains contextes, il est logique de définir votre énumération dans un format non-code, comme un fichier CSV, YAML ou XML, puis de générer à la fois le code d'énumération C ++ et le code de chaîne à partir de la définition. Cette approche peut être pratique ou non dans votre application, mais c'est quelque chose à garder à l'esprit.
la source
Ceci est une modification de la réponse @ user3360260. Il a les nouvelles fonctionnalités suivantes
MyEnum fromString(const string&)
soutienUsage:
Voici le code
Notez que la conversion toString est une recherche rapide, tandis que la conversion fromString est une recherche linéaire lente. Mais les chaînes sont si chères de toute façon (et le fichier associé IO), je n'ai pas ressenti le besoin d'optimiser ou d'utiliser une bimap.
la source
Voici une solution à un fichier (basée sur une réponse élégante de @Marcin:
la source
Je fais cela avec des classes wrapper enum côte à côte séparées qui sont générées avec des macros. Il y a plusieurs avantages:
L'inconvénient, bien sûr, est que je dois dupliquer les valeurs d'énumération dans les classes du formateur, et je n'ai aucun script pour les générer. À part cela, cependant, cela semble fonctionner plutôt bien.
Voici un exemple d'énumération de ma base de code, sans tout le code du framework qui implémente les macros et les modèles, mais vous pouvez avoir l'idée:
L'idée est alors au lieu d'utiliser EHelpLocation, vous utilisez SEHelpLocation; tout fonctionne de la même manière, mais vous obtenez une vérification de plage et une méthode 'Format ()' sur la variable enum elle-même. Si vous devez formater une valeur autonome, vous pouvez utiliser CEnumFormatter_EHelpLocation :: FormatEnum (...).
J'espère que cela est utile. Je me rends compte que cela ne répond pas non plus à la question originale sur un script pour générer réellement l'autre classe, mais j'espère que la structure aidera quelqu'un à essayer de résoudre le même problème ou à écrire un tel script.
la source
C'est un logiciel inédit, mais il semble que BOOST_ENUM de Frank Laub pourrait faire l'affaire. La partie que j'aime à ce sujet est que vous pouvez définir une énumération dans le cadre d'une classe, ce que la plupart des énumérations basées sur les macros ne vous permettent généralement pas de faire. Il est situé dans le Boost Vault à l' adresse : http://www.boostpro.com/vault/index.php?action=downloadfile&filename=enum_rev4.6.zip&directory=& Il n'a vu aucun développement depuis 2006, donc je ne le fais pas savoir à quel point il se compile avec les nouvelles versions de Boost. Regardez sous libs / test pour un exemple d'utilisation.
la source
C'était ma solution avec BOOST:
Pour créer une énumération, déclarez:
Pour les conversions:
la source
Je veux publier ceci au cas où quelqu'un le trouverait utile.
Dans mon cas, j'ai simplement besoin de générer
ToString()
et deFromString()
fonctionner pour une seule énumération C ++ 11 à partir d'un seul.hpp
fichier.J'ai écrit un script python qui analyse le fichier d'en-tête contenant les éléments d'énumération et génère les fonctions dans un nouveau
.cpp
fichier.Vous pouvez ajouter ce script dans CMakeLists.txt avec execute_process ou en tant qu'événement de pré-génération dans Visual Studio. Le
.cpp
fichier sera généré automatiquement, sans qu'il soit nécessaire de le mettre à jour manuellement à chaque fois qu'un nouvel élément d'énumération est ajouté.generate_enum_strings.py
Exemple:
ErrorCode.hpp
Courir
python generate_enum_strings.py ErrorCode.hpp
Résultat:
ErrorCode.cpp
la source
Ajoutant encore plus de simplicité d'utilisation à la réponse fantastique de Jasper Bekkers :
Configurer une fois:
Ensuite, pour l'utilisation:
la source
Vous pouvez utiliser une bibliothèque de réflexion, comme Ponder . Vous enregistrez les énumérations, puis vous pouvez les convertir d'avant en arrière avec l'API.
la source
Un problème avec la réponse 0 est que les valeurs binaires d'énumération ne commencent pas nécessairement à 0 et ne sont pas nécessairement contiguës.
Lorsque j'en ai besoin, je:
la source
Le script ruby suivant tente d'analyser les en-têtes et construit les sources requises à côté des en-têtes d'origine.
L'utilisation d'expressions régulières rend cet "analyseur" assez fragile, il peut ne pas être capable de gérer vos en-têtes spécifiques avec élégance.
Supposons que vous ayez un en-tête toto / ah, contenant des définitions pour les enums MyEnum et MyEnum2. Le script construira:
Des solutions plus robustes seraient:
la source
C'est à peu près la seule façon de le faire (un tableau de chaînes pourrait également fonctionner).
Le problème est qu'une fois qu'un programme C est compilé, la valeur binaire de l'énumération est tout ce qui est utilisé, et le nom a disparu.
la source
Voici un programme CLI que j'ai écrit pour convertir facilement les énumérations en chaînes. Il est facile à utiliser et prend environ 5 secondes pour le faire (y compris le temps de cd dans le répertoire contenant le programme, puis exécutez-le, en lui passant le fichier contenant l'énumération).
Téléchargez ici: http://www.mediafire.com/?nttignoozzz
Sujet de discussion à ce sujet ici: http://cboard.cprogramming.com/projects-job-recruitment/127488-free-program-im-sharing-convertenumtostrings.html
Exécutez le programme avec l'argument "--help" pour obtenir une description de son utilisation.
la source
Il n'y a pas si longtemps, j'ai fait une astuce pour avoir les énumérations correctement affichées dans QComboBox et pour avoir la définition des représentations enum et chaîne comme une seule instruction
Vous pouvez maintenant
enumeration::enum_singleton<your_enum>::instance()
convertir les énumérations en chaînes. Si vous remplacezkv_storage_t
parboost::bimap
, vous pourrez également effectuer une conversion en amont. Une classe de base commune pour le convertisseur a été introduite pour le stocker dans un objet Qt, car les objets Qt ne pouvaient pas être des modèlesApparition précédente
la source
En variante, utilisez simple lib> http://codeproject.com/Articles/42035/Enum-to-String-and-Vice-Versa-in-C
Dans le code
ajouter des lignes
Fonctionne très bien, si les valeurs enum ne sont pas dupliquées .
Exemple d'utilisation
et vice versa
la source
Voici une tentative pour obtenir automatiquement les opérateurs de flux << et >> sur enum avec une commande de macro d'une seule ligne ...
Définitions:
Usage:
Je ne suis pas sûr des limites de ce système ... les commentaires sont les bienvenus!
la source
la source