Qui Typesafe Enum en C++ Utilisez-Vous?
C'est la connaissance commune que construit-dans les énumérations en C++ ne sont pas typesafe.
Je me demandais ce qui les classes de la mise en œuvre de typesafe les enums sont utilisées là-bas...
J'utilise moi-même la suite de "vélo", mais elle est un peu verbeux et limitée:
typesafeenum.h:
struct TypesafeEnum
{
//Construction:
public:
TypesafeEnum(): id (next_id++), name("") {}
TypesafeEnum(const std::string& n): id(next_id++), name(n) {}
//Operations:
public:
bool operator == (const TypesafeEnum& right) const;
bool operator != (const TypesafeEnum& right) const;
bool operator < (const TypesafeEnum& right) const;
std::string to_string() const { return name; }
//Implementation:
private:
static int next_id;
int id;
std::string name;
};
typesafeenum.cpp:
int TypesafeEnum::next_id = 1;
bool TypesafeEnum::operator== (const TypesafeEnum& right) const
{ return id == right.id; }
bool TypesafeEnum::operator!= (const TypesafeEnum& right) const
{ return !operator== (right); }
bool TypesafeEnum::operator< (const TypesafeEnum& right) const
{ return id < right.id; }
Utilisation:
class Dialog
{
...
struct Result: public TypesafeEnum
{
static const Result CANCEL("Cancel");
static const Result OK("Ok");
};
Result doModal();
...
};
const Dialog::Result Dialog::Result::OK;
const Dialog::Result Dialog::Result::CANCEL;
Plus:
Je pense que j'aurais du être plus précis sur les exigences. Je vais essayer de résumer:
Priorité 1: la définition d'un enum variable à une valeur non valide doit être impossible (une erreur de compilation), sans exceptions.
Priorité 2: Conversion d'une valeur d'enum vers/à partir d'un int devrait être possible avec une seule fonction explicite/appel de la méthode.
Priorité 3: compact, élégant et pratique de la déclaration et de l'utilisation possible
Priorité 4: Convertir les valeurs de l'enum et de cordes.
Priorité 5: (optionnel) Possibilité d'effectuer une itération sur les valeurs de l'enum.
- Désolé, ce compilateur utilisez-vous? MSVC 2008 ne peut pas compiler cet exemple. Ce - static const Résultat ANNULER("Annuler"); - ne pas ressembler à un valide le code C++...
- Désolé pour le long retard, probablement pas pertinent, pas plus, mais je vais quand même répondre: c'était mon erreur, la version originale que j'ai eu n'ont pas de cordes, j'ai boulonné sur avant de poster sans vérifier, désolé. La version correcte serait de passer des chaînes à la les valeurs de l'enum' constructeurs dans le fichier cpp.
- c'est actuellement la meilleure question sur les énumérations et les chaînes de caractères dans la sofar.
- J'ai changé les balises de c++03, comme il est expressément tapé les énumérations sont maintenant une partie de C++. Notez que les énumérations où déjà "typesafe" en C++2003.
Vous devez vous connecter pour publier un commentaire.
Je suis en train de jouer avec le coup de pouce.Enum proposition de la Stimuler La Voûte (nom de fichier
enum_rev4.6.zip
). Bien qu'il n'a jamais été officiellement soumis pour inclusion dans Boost, il est utilisable en l'état. (Documentation est incomplète, elle est faite par claire code source et de bons tests.)Coup de pouce.Enum permet de déclarer un enum comme ceci:
Automatiquement étendre à ceci:
Il satisfait à toutes les cinq priorités qui vous liste.
Un bon compromis méthode est: est-ce
Ce n'est pas typesafe dans le même sens que votre version est, mais l'usage en est plus agréable que la norme des enums, et vous pouvez toujours profiter de conversion d'entier quand vous en avez besoin.
- Je utiliser C++0x typesafe enums. J'utilise de la helper modèle/macros qui fournissent les vers/à partir de la chaîne de fonctionnalité.
Je n'ai pas. Beaucoup trop généraux pour peu d'avantages. Aussi, le fait de pouvoir à la caste des énumérations à différents types de données pour la sérialisation est un outil très pratique. Je n'ai jamais vu un cas où un "Type de sécurité" de l'énumération serait la valeur de la surcharge et de la complexité où C++ offre une assez bonne mise en œuvre déjà.
De mon point de vue, c'est que vous êtes en train d'inventer un problème, et puis côté d'une solution sur elle. Je ne vois aucune nécessité de faire élaborer un cadre pour une énumération de valeurs. Si vous êtes dédié pour avoir vos valeurs seulement être membres d'un certain ensemble, vous pouvez pirater une variante d'un jeu unique de type de données.
Je suis personnellement en utilisant une version adaptée de la typesafe enum idiome. Il ne fournit pas tous les cinq "exigences" que vous avez indiqué dans votre modifier, mais je suis en total désaccord avec certains d'entre eux de toute façon. Par exemple, je ne vois pas comment Prio#4 (conversion des valeurs de chaînes de caractères) n'a rien à voir avec le type de sécurité. La plupart du temps, représentation de chaîne de valeurs individuelles doit être distincte de la définition du type, de toute façon (pense i18n pour une simple raison pourquoi). Priorité n ° 5 (iteratio, qui est facultatif) est l'une des plus belles choses que j'aimerais voir naturellement qui se passe dans les énumérations, de sorte que je me sentais triste qu'il apparaît comme "facultatif" dans votre demande, mais il semble que c'est mieux traitée par le biais d'un séparer itération du système d' comme
begin
/end
fonctions ou un enum_iterator, qui fait d'eux de travailler de façon transparente avec STL et C++11 foreach.Otoh, que cette simple idiome bien fournit Priorité N ° 3 Priorité n ° 1 grâce au fait que la plupart du temps que des enveloppements
enum
s avec plus d'informations de type. Sans oublier qu'il est une solution très simple qui, pour la plupart, ne nécessite aucune dépendance externe en-têtes, il est donc assez facile à transporter. Il a aussi l'avantage de faire des énumérations de portée à la C++11:Le seul "trou" cette solution fournit, c'est qu'il ne traite pas le fait que cela ne les empêche pas
enum
s de différents types (ou unenum
et un int) d'être directement comparés, parce que lorsque vous utilisez des valeurs directement vous forcer la conversion implicite enint
:Mais jusqu'à présent, j'ai trouvé ces problèmes peuvent être résolus simplement en offrant une meilleure comparaison pour le compilateur, par exemple, explicitement, en fournissant un opérateur qui compare deux différents
enum
types, puis en les forçant à s'échouer:Bien qu'il ne semble pas casser le code jusqu'à présent, et il ne explicitement traiter le problème spécifique sans faire autre chose, je ne suis pas certain que telle chose est une chose que l'on "devrait" faire (je le soupçonne d'interférer avec
enum
s prend déjà part à des opérateurs de conversion déclaré ailleurs; je serais heureux de recevoir vos commentaires à ce sujet).La combinant avec la au-dessus de typesafe idiome donne quelque chose qui est relativement proche du C++11
enum class
dans humanibility (la lisibilité et la maintenabilité) sans avoir à faire quelque chose de trop obscur. Et je dois avouer que c'était amusant à faire, je n'avais jamais pensé à fait demander le compilateur si j'avais à faire avecenum
s ou pas...typesafe_enum
- une chance de montrer le code pour cela? Il est difficile de comprendre la réponse dans le cas contraire (à moins que je suis absent quelque chose d'évident).typesafe_enum
dans Wikibooks (que j'ai également lié ci-dessus). J'ai ajouté à cela un couple de macros à la fois de faire des déclarations plus simple et de le rendre compatible avec le C++11. Peut-être que je devrais le poster quelque part.Je pense que le Java
enum
serait un bon modèle à suivre. Essentiellement, la Java formulaire devrait ressembler à ceci:Ce qui est intéressant à propos de l'Java approche est que
OK
etCANCEL
sont immuables, singleton instances deResult
(avec les méthodes que vous voyez). Vous ne pouvez créer d'autres instances deResult
. Car ils sont des singletons, vous pouvez comparer par pointeur/référence---très pratique. 🙂ETA: En Java, au lieu de faire des masques de bits à la main, à la place, vous utilisez un
EnumSet
pour spécifier un ensemble de bits (il met en œuvre laSet
interface, et fonctionne comme le définit---mais, mis en place à l'aide de masques de bits). Beaucoup plus lisible que la main écrit masque de manipulation!<
des comparaisons sur les pointeurs, seulement==
ou!=
. Donc, tant qu'ils sont distincts, ce qui est bon, pour les comparer par pointeur. 🙂 Je vais voir si je peux écrire une implémentation C++ de temps en temps.J'ai donné une réponse à cette ici, sur un thème différent. C'est un style différent de l'approche qui permet à la plupart des mêmes fonctionnalités sans nécessiter de modification de l'original enum définition (et, par conséquent, permettant l'utilisation dans le cas où vous ne définissez pas l'enum). Il permet également d'exécution le contrôle de la portée.
L'inconvénient de cette approche est qu'il n'est pas par programmation appliquer le couplage entre l'enum et de la classe d'aide, de sorte qu'ils doivent être mis à jour en parallèle. Il fonctionne pour moi, mais YMMV.
Je suis en train d'écrire mon propre typesafe enum bibliothèque https://bitbucket.org/chopsii/typesafe-enums
Je ne suis pas le plus expérimenté, développeur C++, jamais, mais je suis en train d'écrire ce dû aux insuffisances de la poussée de la voûte des enums.
Hésitez pas à les tester et de les utiliser vous-même, mais ils ont quelques (espérons-le mineur) problèmes d'utilisation, et ne sont probablement pas à tous de la croix-plate-forme.
Merci de contribuer si vous le souhaitez. C'est mon premier open source d'entreprise.
Utilisation
boost::variant
!Après avoir essayé beaucoup de les idées ci-dessus et de leur trouver un défaut, je suis tombé sur cette approche simple:
Vous pouvez probablement venir avec une macro pour générer le code. (Laissez-moi savoir si vous faites).
Contrairement à d'autres approches celui-ci est en fait de type sécurisé et fonctionne avec des vieux C++. Vous pouvez même les faire refroidir types comme
boost::variant<int, A_t, B_t, boost::none>
, par exemple, pour représenter une valeur qui pourrait être Un, B, entier ou rien de ce qui est presque Haskell98 les niveaux de sécurité de type.Inconvénients d'être conscient de:
Mise à jour
Ici, pour votre commodité, votre typesafe-enum "bibliothèque". Collez cet en-tête:
Et de l'utiliser comme:
Avis que vous avez à dire
A_t
au lieu deA
dans leENUM
macro qui détruit une partie de la magie. Oh bien. Aussi, notez qu'il y a maintenant untoStr
fonction et untoInt
fonction pour répondre OPs exigence de la simple conversion de chaînes et de services de renseignements. L'exigence je ne peux pas comprendre est une façon d'itérer sur les éléments. Laissez-moi savoir si vous savez comment écrire une telle chose.Ne sais pas si ce post est trop tard, mais il y a un article sur GameDev.net qui répond à l'ensemble mais le 5ème point (capacité à effectuer une itération sur les agents recenseurs):
http://www.gamedev.net/reference/snippets/features/cppstringizing/
La méthode décrite par l'article permet la conversion de chaîne de soutien pour existant énumérations sans modification de leur code. Si vous voulez seulement un soutien pour les nouveaux énumérations bien, j'irais avec Boost.Enum (mentionné ci-dessus).