EDIT in risposta alla chiarificazione
La tua idea di prendere il modulo iteratore COUNT
su ogni dereference è un buon compromesso. Vedere l'iteratore al rovescio/combinazione iterabile sotto. Ho controllato l'output del gruppo dopo aver compilato clang con -O3
. Il compilatore ha srotolato il ciclo. L'output è 2 1 0 5 4 3
. È possibile implementare un iteratore in avanti o impostare la direzione come parametro. Puoi anche trasformarlo in un modello sopra il tipo enum.
Purtroppo, dal punto di vista della sintassi utilizzo, non credo che questo si acquista più di tanto nel corso di un do
- while
ciclo come dimostra l'altra risposta - almeno non prima di C++ 11. Nasconde le varie variabili dell'indice e aiuta a evitare errori con loro, ma è molto più dettagliato.
#include <iostream>
struct Direction {
enum Type {N, NE, SE, S, SW, NW};
static const unsigned COUNT = 6;
Type t_;
operator Type() { return t_; }
Direction(Type t) : t_(t) { }
explicit Direction(unsigned t) : t_(Type(t % COUNT)) { }
};
struct ReverseIterable {
const unsigned start_;
struct iterator {
unsigned offset_;
explicit iterator(unsigned offset) : offset_(offset) { }
Direction operator *() { return Direction(offset_); }
iterator& operator++() { --offset_; return *this; }
bool operator ==(const iterator &other)
{ return offset_ == other.offset_; }
bool operator !=(const iterator &other) { return !(*this == other); }
};
explicit ReverseIterable(Direction start) : start_(start) { }
iterator begin() { return iterator(start_ + Direction::COUNT); }
iterator end() { return iterator(start_); }
};
int main()
{
ReverseIterable range = ReverseIterable(Direction::SE);
for (ReverseIterable::iterator iterator = range.begin();
iterator != range.end(); ++iterator) {
std::cout << (int)*iterator << " ";
}
std::cout << std::endl;
return 0;
}
In C++ 11, il ciclo potrebbe essere:
for (Direction direction : ReverseIterable(Direction::SE))
std::cout << (int)direction << " ";
std::cout << std::endl;
Probabilmente si può (? Ab) usare una macro per ottenere qualcosa di simile in C++ 98.
Ho mantenuto la risposta originale qui sotto per il momento, perché semplifica la manutenibilità se la definizione enum può cambiare e perché consente intervalli sparsi. Un iteratore molto simile può essere implementato sopra di esso.
risposta originale incentrata sulla sicurezza
Questo potrebbe essere eccessivo completo per il vostro scopo, e potrebbe essere poco adatto per un motivo mi limiterò a descrivere più in basso.Tuttavia, è possibile utilizzare questa libreria (disclaimer: io sono l'autore): https://github.com/aantron/better-enums di scrivere codice come questo:
#include <iostream>
#include <enum.h>
ENUM(Direction, int, N, NE, SE, S, SW, NW)
int main()
{
size_t iterations = Direction::_size();
size_t index = 2;
for (size_t count = 0; count < iterations; ++count) {
std::cout << Direction::_values()[index] << " ";
index = (index + 1) % Direction::_size();
}
std::cout << std::endl;
return 0;
}
uscita:
SE S SW NW N NE
(I valori erano int
enumerazioni -sized, ma erano convertito in stringhe per l'output solo su std::cout
).
Questo mostra un'iterazione sull'intero insieme, con un punto di partenza arbitrario. Puoi farlo andare avanti o indietro e templatizzarlo su qualsiasi enumerazione.
Penso che usare modulo come nella tua domanda sia una buona idea. Questo codice fornisce solo alcune informazioni riflettenti sul numero di costanti nell'enumerazione e le inserisce in un array.
Il motivo per cui questo potrebbe non essere adatto è che, poiché non si utilizza C++ 11, l'array Direction::_values()
verrà inizializzato all'avvio del programma. Penso che lo svolgimento del ciclo possa ancora accadere, ma il compilatore non sarà in grado di fare nulla con il contenuto dell'array. La matrice verrà comunque allocata staticamente, ma gli elementi non saranno disponibili durante la compilazione.
caso più tardi avere la possibilità di utilizzare C++ 11, l'array sarà sostanzialmente lo stesso di un staticamente-inizializzato int[6]
(in realtà, Direction[6]
, dove Direction
è un letterale struct
tipo).
(In realtà, suppongo di poter esporre un array di int
s invece di Direction
s, che sarebbe stato inizializzato staticamente anche in C++ 98).
Nessun codice funzionante nella domanda. Il codice postato è semplicemente la struttura di un enum a cui si riferisce la domanda. Ciò che è pubblicato sotto il codice sta iniziando idee non più – Flamefire
Mi dispiace, mio errore! –