9 Stimmen

Schleife über Aufzählungswerte

Wie schlimm ist es - oder ist es völlig akzeptabel -, eine Schleife über eine Aufzählung zu indizieren?

Ich habe eine Aufzählung definiert. Die Werte der Literale sind Standardwerte. Die zugewiesenen Werte haben keine Bedeutung, werden keine Bedeutung haben und auch die Werte aller in Zukunft hinzugefügten Literale werden keine Bedeutung haben. Es wird nur definiert, um die erlaubten Werte einzuschränken und die Verfolgung von Dingen zu erleichtern. Daher werden die Werte immer bei 0 beginnen und um 1 erhöht werden.

Kann ich eine Schleife wie folgt einrichten:

enum MeineAufzählung
{
    wert1,
    wert2,
    wert3,
    maxWert
}

for(MeineAufzählung i = wert1; i < maxWert; i = static_cast(i+1)){}

9voto

Ich habe vor einiger Zeit einen Enum-Iterator für diese Fälle geschrieben

enum Foo {
 A, B, C, Last
};

typedef litb::enum_iterator FooIterator;

int main() {
  FooIterator b(A), e;
  std::cout << std::distance(b, e)  << " Werte:" << std::endl;
  std::copy(b, e, std::ostream_iterator(std::cout, "\n"));

  while(b != e) doIt(*b++);
}

Wenn Sie interessiert sind, hier ist der Code. Falls Sie möchten, können Sie ihn erweitern, um ein Random-Access-Iterator zu sein, indem Sie +, <, [] und ähnliches bereitstellen. Algorithmen wie std::distance werden Ihnen danken, indem sie für den dann Random-Access-Iterator eine Zeitkomplexität von O(1) bieten.

#include 

namespace litb {

template
struct enum_iterator 
  : std::iterator {
  enum_iterator():c(End) { }
  enum_iterator(Enum c):c(c) { }

  enum_iterator &operator=(Enum c) {
    this->assign(c);
    return *this;
  }

  enum_iterator &operator++() {
    this->inc();
    return *this;
  }

  enum_iterator operator++(int) {
    enum_iterator cpy(*this);
    this->inc();
    return cpy;
  }

  enum_iterator &operator--() {
    this->dec();
    return *this;
  }

  enum_iterator operator--(int) {
    enum_iterator cpy(*this);
    this->dec();
    return cpy;
  }

  Enum operator*() const {
    assert(c != End && "nicht dereferenzierbar!");
    return c;
  }

  bool equals(enum_iterator other) const {
    return other.c == c;
  }

private:
  void assign(Enum c) {
    assert(c >= Begin && c <= End);
    this->c = c; 
  }

  void inc() {
    assert(c != End && "Über das Ende hinaus inkrementieren");
    c = static_cast(c + 1);
  }

  void dec() {
    assert(c != Begin && "Über den Anfang hinaus dekrementieren");
    c = static_cast(c - 1);
  }

private:
  Enum c;
};

template
bool operator==(enum_iterator e1, enum_iterator e2) {
  return e1.equals(e2);
}

template
bool operator!=(enum_iterator e1, enum_iterator e2) {
  return !(e1 == e2);
}

} // litb

4voto

Carl Norum Punkte 210051

Soweit ich das beurteilen kann, ist das in Ordnung. Ich bin sicher, dass irgendwo da draußen ein Purist ausrasten wird, aber was die Sprachspezifikation betrifft, wird dieser Code korrekt funktionieren, also können Sie ihn verwenden, wenn es Ihr Leben erleichtert.

2voto

thereisnospork Punkte 193

Es könnte hilfreich sein, das zu tun.

enum MyEnum
{
    first,
    value1,
    value2,
    value3,
    last
}

0voto

R Samuel Klatchko Punkte 72641

Das ist in Ordnung, solange Sie den Wert eines Enumerationswerts nicht explizit festlegen. Ihr Beispiel ist in Ordnung, aber das hier könnte schlecht sein:

// das wäre schlecht
enum MeinEnum
{
    Wert1,
    Wert2 = 2,
    Wert3,
    MaximalWert
};

Wie im Standard in 7.2/1 angegeben:

Ein Enumerationsdefinition ohne Initialisierer gibt dem Enumerator den Wert, der durch Erhöhen des Werts des vorherigen Enumerators um eins erhalten wird.

0voto

fabrizioM Punkte 43906

Ich kenne keine spezifische Verwendung davon, die tatsächlich nützlich ist und ich denke, dass es schlechter Code ist. Was ist, wenn man Dinge so wie in vielen Bibliotheken sieht ?

enum MyEnum
{
    value1,
    value2,
    value3,
    maxValue = 99999;
};

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X