¿Cómo puedo generar el valor de an enum class
en C ++ 11? En C ++ 03 es así:
#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 este código no se compila
#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]'
compilado en Ideone.com
Respuestas:
A diferencia de una enumeración sin ámbito, una enumeración con ámbito no se puede convertir implícitamente en su valor entero. Necesita convertirlo explícitamente en un número entero usando una conversión:
Es posible que desee encapsular la lógica en una plantilla de función:
Usado como:
fuente
as_integer
de una de mis bibliotecas de código abierto, CxxReflect (ver enumeration.hpp ). La biblioteca usa tipos de retorno finales de manera consistente, en todas partes. Por consistencia.as_integer
se puede definir paraconstexpr
que se pueda usar en contextos donde se necesita una expresión constante.fuente
g++ -std=c++0x enum.cpp
pero recibo un montón de errores de compilación -> pastebin.com/JAtLXan9 . Tampoco pude obtener el ejemplo de @ james-mcnellis para compilar.Es posible hacer que su segundo ejemplo (es decir, el que usa una enumeración con ámbito) funcione usando la misma sintaxis que las enumeraciones sin ámbito. Además, la solución es genérica y funcionará para todas las enumeraciones con ámbito, en lugar de escribir código para cada enumeración con ámbito (como se muestra en la respuesta proporcionada por @ForEveR ).
La solución es escribir una
operator<<
función genérica que funcione para cualquier enumeración con ámbito. La solución emplea SFINAE víastd::enable_if
y es la siguiente.fuente
typename
antesstd::underlying_type<T>::type
.error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
. esto parece deberse a que cuando la transmisión es temporal, la ADL falla y la plantilla anterior no es posible. ¿algun consejo?cout
declaraciones en una solacout
declaración encadenando los<<
operadores. Vea aquí(No puedo comentar todavía). Sugeriría las siguientes mejoras a la ya excelente respuesta de James McNellis:
con
constexpr
: permitiéndome usar un valor de miembro de enumeración como tamaño de matriz en tiempo de compilaciónstatic_assert
+is_enum
: para 'asegurar' en tiempo de compilación que la función hace algo. solo con enumeraciones, como se sugierePor cierto, me pregunto: ¿Por qué debería usar
enum class
cuando me gustaría asignar valores numéricos a los miembros de mi enumeración? Considerando el esfuerzo de conversión.Quizás luego volvería a lo ordinario
enum
como sugerí aquí: ¿Cómo usar enumeraciones como indicadores en C ++?Otro sabor (mejor) sin static_assert, basado en una sugerencia de @TobySpeight:
fuente
T
para el questd::underlying_type<T>::type
existe, perostd::is_enum<T>::value
es falso? Si no es así, nostatic_assert
agrega valor.Enumeration
no es un tipo de enumeración completo. En cuyo caso, puede que ya sea demasiado tarde, ya que se usa en el tipo de devolución. ¿Quizás podríamos especificarstd::enable_if<std::is_enum<Enumeration>::value, std::underlying_type<Enumeration>::type>
como tipo de retorno? Por supuesto, es mucho más fácil (y los mensajes de error mucho más claros) si tiene un compilador compatible con Concepts ...Para escribir más simple,
fuente
Lo siguiente funcionó para mí en C ++ 11:
fuente
Podrías hacer algo como esto:
fuente