137 votes

Existe-t-il un script simple permettant de convertir une énumération C ++ en chaîne?

Supposons que nous avons une certaine nommé les énumérations:

enum MyEnum {
      FOO,
      BAR = 0x50
};

Ce que j'ai cherché sur google un script (toutes les langues) qui scanne tous les en-têtes dans mon projet et génère un en-tête avec une fonction par le protocole enum.

char* enum_to_string(MyEnum t);

Et une mise en œuvre avec quelque chose comme ceci:

char* enum_to_string(MyEnum t){
      switch(t){
         case FOO:
            return "FOO";
         case BAR:
            return "BAR";
         default:
            return "INVALID ENUM";
      }
 }

Gotcha est vraiment avec typedefed enums, et sans nom de style C enums. Quelqu'un sait quelque chose pour cela?

EDIT: La solution ne doit pas modifier ma source, sauf pour le générés fonctions. Les énumérations sont dans une API, en utilisant les solutions proposées jusqu'à présent n'est tout simplement pas une option.

75voto

Marcin Koziuk Points 478

Les macros X sont la meilleure solution. Exemple:

 #include <iostream>

enum Colours {
#   define X(a) a,
#   include "colours.def"
#   undef X
    ColoursCount
};

char const* const colours_str[] = {
#   define X(a) #a,
#   include "colours.def"
#   undef X
    0
};

std::ostream& operator<<(std::ostream& os, enum Colours c)
{
    if (c >= ColoursCount || c < 0) return os << "???";
    return os << colours_str[c];
}

int main()
{
    std::cout << Red << Blue << Green << Cyan << Yellow << Magenta << std::endl;
}
 

colours.def:

 X(Red)
X(Green)
X(Blue)
X(Cyan)
X(Yellow)
X(Magenta)
 

Cependant, je préfère généralement la méthode suivante, afin qu'il soit possible d'ajuster légèrement la chaîne.

 #define X(a, b) a,
#define X(a, b) b,

X(Red, "red")
X(Green, "green")
// etc.
 

50voto

Avdi Points 13086

Vous voudrez peut-être consulter GCCXML .

L'exécution de GCCXML sur votre exemple de code produit:

 <GCC_XML>
  <Namespace id="_1" name="::" members="_3 " mangled="_Z2::"/>
  <Namespace id="_2" name="std" context="_1" members="" mangled="_Z3std"/>
  <Enumeration id="_3" name="MyEnum" context="_1" location="f0:1" file="f0" line="1">
    <EnumValue name="FOO" init="0"/>
    <EnumValue name="BAR" init="80"/>
  </Enumeration>
  <File id="f0" name="my_enum.h"/>
</GCC_XML>
 

Vous pouvez utiliser la langue de votre choix pour extraire les balises Enumeration et EnumValue et générer le code souhaité.

50voto

Jasper Bekkers Points 4949

@hydroo: Sans le fichier supplémentaire:

 #define SOME_ENUM(DO) \
    DO(Foo) \
    DO(Bar) \
    DO(Baz)

#define MAKE_ENUM(VAR) VAR,
enum MetaSyntacticVariable{
    SOME_ENUM(MAKE_ENUM)
}

#define MAKE_STRINGS(VAR) #VAR,
const char* const MetaSyntacticVariableNames[] = {
    SOME_ENUM(MAKE_STRINGS)
}
 

36voto

gbjbaanb Points 31045

Ce que j'ai tendance à faire est de créer un C tableau avec les noms dans le même ordre et la position que les valeurs enum.

par exemple.

enum colours { red, green, blue };
char* array[] colour_names = { "red", "green", "blue" };

ensuite, vous pouvez utiliser le tableau dans les endroits où vous voulez lisible par l'utilisateur de la valeur, par exemple

colours mycolour = red;
cout << "the colour is" << colour_names[mycolour];

Vous pourriez expérimenter un peu avec les stringizing opérateur (voir # dans votre préprocesseur de référence) qui permettra de faire ce que vous voulez, dans certaines circonstances - par exemple:

#define printword(XX) cout << #XX;
printword(red);

imprimé "rouge" sur la sortie standard stdout. Malheureusement, il ne fonctionnera pas pour une variable (que vous aurez le nom de la variable imprimé)

8voto

Ronny Brendel Points 2588

QT est capable de tirer celui de (grâce au compilateur de méta-objets): link

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X