135 votes

Comment associer facilement c ++ enums en chaînes

J'ai un tas de types enum dans une bibliothèque fichiers d'en-tête que j'utilise, et je veux avoir un moyen de convertir les valeurs de l'enum à l'utilisateur cordes, et vice-versa.

RTTI de ne pas le faire pour moi, parce que l '" utilisateur cordes besoin d'être un peu plus lisible que les énumérations.

Une attaque par force brute solution serait un tas de fonctions de ce genre, mais j'ai l'impression que c'est un peu trop C-like.

enum MyEnum {VAL1, VAL2,VAL3};

String getStringFromEnum(MyEnum e)
{
  switch e
  {
  case VAL1: return "Value 1";
  case VAL2: return "Value 2";
  case VAL1: return "Value 3";
  default: throw Exception("Bad MyEnum");
  }
}

J'ai le pressentiment qu'il y a une solution élégante à l'aide de modèles, mais je n'arrive pas à obtenir ma tête autour de lui encore.

Mise à JOUR: Merci pour les suggestions - j'aurais dû préciser que les enums sont définies dans une bibliothèque tierce, en-tête, donc je ne veux pas avoir à modifier la définition d'entre eux.

Mon sentiment profond est maintenant pour éviter de modèles et de faire quelque chose comme ceci:

char * MyGetValue(int v, char *tmp); // implementation is trivial

#define ENUM_MAP(type, strings) char * getStringValue(const type &T) \
 { \
 return MyGetValue((int)T, strings); \
 }

; enum eee {AA,BB,CC}; - exists in library header file 
; enum fff {DD,GG,HH}; 

ENUM_MAP(eee,"AA|BB|CC")
ENUM_MAP(fff,"DD|GG|HH")

// To use...

	eee e;
	fff f;
	std::cout<< getStringValue(e);
	std::cout<< getStringValue(f);

65voto

MSalters Points 74024

Si vous voulez l'énumération des noms eux-mêmes comme des chaînes de caractères, voir ce post. Sinon, std::map<MyEnum, char const*> fonctionnent bien. (Pas de point dans la copie de votre littéraux de chaîne à std::chaînes à la carte)

Pour plus de sucre syntaxique, voici comment écrire un map_init classe. L'objectif est de permettre

std::map<MyEnum, const char*> MyMap;
map_init(MyMap)
    (eValue1, "A")
    (eValue2, "B")
    (eValue3, "C")
;

La fonction template <typename T> map_init(T&) renvoie un map_init_helper<T>. map_init_helper<T> magasins de T&, et définit le trivial map_init_helper& operator()(typename T::key_type const&, typename T::value_type const&). (De retour *this de operator() permet le chaînage de operator(), comme operator<< sur std::ostreams)

template<typename T> struct map_init_helper
{
    T& data;
    map_init_helper(T& d) : data(d) {}
    map_init_helper& operator() (typename T::key_type const& key, typename T::mapped_type const& value)
    {
        data[key] = value;
        return *this;
    }
};

template<typename T> map_init_helper<T> map_init(T& item)
{
    return map_init_helper<T>(item);
}

Puisque la fonction et de la classe helper sont basés sur des modèles, vous pouvez les utiliser pour n'importe quelle carte, ou de la carte-comme la structure. I. e. il peut également ajouter des entrées à l' std::unordered_map

Si vous n'aimez pas écrire ces aides, boost::attribuer offre les mêmes fonctionnalités de la boîte.

33voto

Alastair Points 2491

MSalters solution est bonne mais fondamentalement ré-implémente `` . Si vous avez Poussée, vous pouvez l’utiliser directement :

21voto

J.F. Sebastian Points 102961

Générer automatiquement une forme de l’autre.

Source :

Généré :

Si les valeurs enum sont grandes alors un formulaire généré pourrait utiliser unordered_map ou modèles tel que suggéré par Constantin.

Source :

Généré :

Exemple :

12voto

David Allan Finch Points 909

Je propose un mélange d’utiliser X-macros sont la meilleure solution et les fonctions de modèle suivant :

Pour emprunter au large de marcinkoziukmyopenidcom et prolongée

Colour.def

11voto

Debdatta Basu Points 31

Je me souviens avoir répondu cela ailleurs sur StackOverflow. Le répéter ici. Fondamentalement, c’est une solution basée sur les variadic macros et est assez facile à utiliser :

Pour l’utiliser dans votre code, il suffit de faire :

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