¿Hay alguna manera de verificar en C ++ 11 si una enumeración es continua ?
Es totalmente válido dar valores enum que no lo son. ¿Hay tal vez una característica como un rasgo de tipo en C ++ 14, C ++ 17 o tal vez C ++ 20 para verificar si la enumeración es continua? Esto se utilizará en un static_assert.
Sigue un pequeño ejemplo:
enum class Types_Discontinuous {
A = 10,
B = 1,
C = 100
};
enum class Types_Continuous {
A = 0,
B = 1,
C = 2
};
static_assert(SOME_TEST<Types_Discontinuous>::value, "Enum should be continuous"); // Fails
static_assert(SOME_TEST<Types_Continuous>::value, "Enum should be continuous"); // Passes
enum
. Lamentablemente tengo un trabajo diario, así que no puedo intentar escribir esto, aunque votaré una respuesta basada en este enfoque. Estoy bastante seguro de que alguien como @barry o @sehe podría hacerlo.static_assert
)? Incluso si no puede hacer una "solución hermosa", escriba una respuesta de todos modos, ya que tengo mucha curiosidad por cómo se podría hacer de manera genérica.Respuestas:
Durante varios
enum
s, probablemente puedas hackear esto usando la biblioteca Magic Enum . Por ejemplo:Tenga en cuenta que esto es, como el nombre de la biblioteca implica, "mágico": la biblioteca funciona en varios hacks específicos del compilador. Como tal, realmente no cumple con su requisito de "C ++ puro", pero probablemente sea tan bueno como podamos obtener hasta que tengamos facilidades de reflexión en el lenguaje.
fuente
Esto no es posible en C ++ puro, porque no hay forma de enumerar los valores de enumeración, o descubrir el número de valores y los valores mínimos y máximos. Pero podría intentar usar la ayuda de su compilador para implementar algo similar a lo que desea. Por ejemplo, en gcc es posible aplicar un error de compilación si una
switch
instrucción no maneja todos los valores de una enumeración:Obviamente, esto está especializado para una enumeración dada, pero la definición de tales funciones puede automatizarse con un preprocesador.
fuente
Me encantaría ver una respuesta sobre esto. Lo he estado necesitando también.
Desafortunadamente, no creo que esto sea posible utilizando las utilidades existentes. Si desea implementar un rasgo de tipo en esto, necesita soporte de su compilador, por lo que escribir una plantilla no parece factible.
Ya extendí la enumeración con una etiqueta específica para indicar que es contigua e inmediatamente le da el tamaño: enum class constructor c ++, ¿cómo pasar un valor específico?
Alternativamente, puedes escribir tu propio rasgo:
Esto debe especializarse cada vez que defina una enumeración contigua donde desea utilizar esto. Desafortunadamente, esto requiere un poco de mantenimiento y atención si se cambia la enumeración.
fuente
Todas las enumeraciones son continuas. 0 siempre está permitido; el valor más alto permitido es el enumerador más alto redondeado al siguiente
1<<N -1
(todos los bits uno), y todos los valores intermedios también están permitidos. ([dcl.enum] 9.7.1 / 5). Si hay enumeradores negativos definidos, el valor más bajo permitido se define de manera similar al redondear el enumerador más bajo.Los enumeradores definidos en el
enum
son expresiones constantes con un valor en el rango y el tipo correcto, pero puede definir constantes adicionales fuera delenum
que tienen las mismas propiedades:constexpr enum class Types_Discontinuous = static_cast<Types_Discontinuous>(2)
fuente