Comment puis-je générer la valeur d'un enum class
en C ++ 11? En C ++ 03, c'est comme ça:
#include <iostream>
using namespace std;
enum A {
a = 1,
b = 69,
c= 666
};
int main () {
A a = A::c;
cout << a << endl;
}
en c ++ 0x ce code ne compile pas
#include <iostream>
using namespace std;
enum class A {
a = 1,
b = 69,
c= 666
};
int main () {
A a = A::c;
cout << a << endl;
}
prog.cpp:13:11: error: cannot bind 'std::ostream' lvalue to 'std::basic_ostream<char>&&'
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/ostream:579:5: error: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char, _Traits = std::char_traits<char>, _Tp = A]'
compilé sur Ideone.com
Réponses:
Contrairement à une énumération non cadrée, une énumération étendue n'est pas implicitement convertible en sa valeur entière. Vous devez le convertir explicitement en entier à l'aide d'un cast:
Vous souhaiterez peut-être encapsuler la logique dans un modèle de fonction:
utilisé comme:
la source
as_integer
partir de l'une de mes bibliothèques open-source, CxxReflect (voir enumeration.hpp ). La bibliothèque utilise les types de retour de fin de manière cohérente, partout. Pour la cohérence.as_integer
peut être défini deconstexpr
manière à pouvoir être utilisé dans des contextes où une expression constante est nécessaire.la source
g++ -std=c++0x enum.cpp
ai compilé comme mais j'obtiens un tas d'erreurs de compilation -> pastebin.com/JAtLXan9 . Je n'ai pas non plus pu obtenir l'exemple de @ james-mcnellis à compiler.Il est possible de faire fonctionner votre deuxième exemple (c'est-à-dire celui qui utilise une énumération à portée) en utilisant la même syntaxe que les énumérations sans portée. De plus, la solution est générique et fonctionnera pour toutes les énumérations de portée, par opposition à l'écriture de code pour chaque énumération de portée (comme indiqué dans la réponse fournie par @ForEveR ).
La solution consiste à écrire une
operator<<
fonction générique qui fonctionnera pour toute énumération de portée. La solution utilise SFINAE viastd::enable_if
et est la suivante.la source
typename
avantstd::underlying_type<T>::type
.error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
. cela semble être dû au fait que lorsque le flux est temporaire, l'ADL échoue et le modèle ci-dessus n'est pas une possibilité. des conseils?cout
instructions en une seulecout
instruction en enchaînant les<<
opérateurs ensemble. Voir ici(Je ne suis pas encore autorisé à commenter.) Je suggérerais les améliorations suivantes à la réponse déjà excellente de James McNellis:
avec
constexpr
: me permettant d'utiliser une valeur de membre enum comme taille de tableau au moment de la compilationstatic_assert
+is_enum
: pour 'assurer' à la compilation que la fonction fait qc. avec énumérations seulement, comme suggéréAu fait, je me demande: pourquoi devrais-je utiliser
enum class
quand je voudrais attribuer des valeurs numériques à mes membres enum?! Compte tenu de l'effort de conversion.Peut-être que je retournerais alors à l'ordinaire
enum
comme je l'ai suggéré ici: Comment utiliser les énumérations comme indicateurs en C ++?Encore une autre (meilleure) saveur sans static_assert, basée sur une suggestion de @TobySpeight:
la source
T
pour lequelstd::underlying_type<T>::type
existe, mais quistd::is_enum<T>::value
est faux? Sinon, alorsstatic_assert
n'ajoute aucune valeur.Enumeration
n'est pas un type enum complet. Dans ce cas, il est peut-être déjà trop tard, car il est utilisé dans le type de retour. Peut-être pourrions-nous spécifierstd::enable_if<std::is_enum<Enumeration>::value, std::underlying_type<Enumeration>::type>
comme type de retour? Bien sûr, c'est tellement plus facile (et les messages d'erreur tellement plus clairs) si vous avez un compilateur prenant en charge les concepts ...Pour écrire plus simple,
la source
La suite a travaillé pour moi en C ++ 11:
la source
Vous pouvez faire quelque chose comme ceci:
la source