Saltar al contenido

¿Cómo puedo iterar sobre una enumeración?

Recuerda que en las ciencias un error suele tener varias resoluciones, por lo tanto nosotros compartimos lo más óptimo y mejor.

Solución:

La forma típica es la siguiente:

enum Foo 
  One,
  Two,
  Three,
  Last
;

for ( int fooInt = One; fooInt != Last; fooInt++ )

   Foo foo = static_cast(fooInt);
   // ...

Tenga en cuenta que la enumeración Last está destinado a ser omitido por la iteración. Utilizando este “falso” Last enumeración, no tiene que actualizar su condición de terminación en el bucle for a la última enumeración “real” cada vez que desee agregar una nueva enumeración. Si desea agregar más enumeraciones más tarde, simplemente agréguelas antes de Último. El bucle de este ejemplo seguirá funcionando.

Por supuesto, esto se descompone si se especifican los valores de enumeración:

enum Foo 
  One = 1,
  Two = 9,
  Three = 4,
  Last
;

Esto ilustra que una enumeración no está realmente destinada a iterar. La forma típica de lidiar con una enumeración es usarla en una declaración de cambio.

switch ( foo )

    case One:
        // ..
        break;
    case Two:  // intentional fall-through
    case Three:
        // ..
        break;
    case Four:
        // ..
        break;
     default:
        assert( ! "Invalid Foo enum value" );
        break;

Si realmente desea enumerar, rellene los valores de enumeración en un vector e itere sobre eso. Esto también se ocupará correctamente de los valores de enumeración especificados.

#include 
#include 

namespace MyEnum

  enum Type
  
    a = 100,
    b = 220,
    c = -1
  ;

  static const Type All[] =  a, b, c ;


void fun( const MyEnum::Type e )

  std::cout << e << std::endl;


int main()

  // all
  for ( const auto e : MyEnum::All )
    fun( e );

  // some
  for ( const auto e :  MyEnum::a, MyEnum::b  )
    fun( e );

  // all
  std::for_each( std::begin( MyEnum::All ), std::end( MyEnum::All ), fun );

  return 0;

Con c ++ 11, en realidad hay una alternativa: escribir un iterador personalizado simple con plantilla.

supongamos que su enumeración es

enum class foo 
  one,
  two,
  three
;

Este código genérico hará el truco, de manera bastante eficiente: colóquelo en un encabezado genérico, le servirá para cualquier enumeración que necesite iterar:

#include 
template < typename C, C beginVal, C endVal>
class Iterator 
  typedef typename std::underlying_type::type val_t;
  int val;
public:
  Iterator(const C & f) : val(static_cast(f)) 
  Iterator() : val(static_cast(beginVal)) 
  Iterator operator++() 
    ++val;
    return *this;
  
  C operator*()  return static_cast(val); 
  Iterator begin()  return *this;  //default ctor is good
  Iterator end() 
      static const Iterator endIter=++Iterator(endVal); // cache it
      return endIter;
  
  bool operator!=(const Iterator& i)  return val != i.val; 
;

Tendrás que especializarlo

typedef Iterator fooIterator;

Y luego puedes iterar usando range-for

for (foo i : fooIterator() )  //notice the parentheses!
   do_stuff(i);

La suposición de que no tiene lagunas en su enumeración sigue siendo true; no hay ninguna suposición sobre la cantidad de bits que realmente se necesitan para almacenar el valor de enumeración (gracias a std::underlying_type)

Más adelante puedes encontrar las anotaciones de otros administradores, tú aún puedes mostrar el tuyo si lo crees conveniente.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : / /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *