Bagaimana saya bisa mengulangi enum?

304

Saya hanya memperhatikan bahwa Anda tidak dapat menggunakan operator matematika standar pada enum seperti ++ atau + =

Jadi apa cara terbaik untuk beralih melalui semua nilai dalam C ++ enum?

Adam
sumber
2
Salah satu dari banyak pendekatan: Ketika enum Hanya Tidak Cukup: Kelas Enumerasi untuk C ++ . Dan, jika Anda menginginkan sesuatu yang lebih terbungkus, coba pendekatan ini dari James Kanze.
Don Wakefield
Item tertaut memiliki beberapa respons menarik.
Tony
Jawaban ini sepertinya tidak mencakup masalah yang intmungkin tidak cukup besar! ( [C++03: 7.2/5])
Lightness Races in Orbit
Menariknya, Anda dapat menentukan operator++pada enum; Namun, jadi Anda bisa melakukannya for(Enum_E e = (Enum_E)0; e < ENUM_COUNT; e++). Catatan Anda harus cor 0untuk Enum_Ekarena operator C ++ larang tugas pada enum.
weberc2
Jika ada operator waktu kompilasi, mirip dengan cara sizeof bekerja, yang dapat memancarkan literal std :: initializer_list yang terdiri dari nilai-nilai enum, kami akan memiliki solusi dan tidak akan melibatkan overhead runtime.
jbruni

Jawaban:

263

Cara khasnya adalah sebagai berikut:

enum Foo {
  One,
  Two,
  Three,
  Last
};

for ( int fooInt = One; fooInt != Last; fooInt++ )
{
   Foo foo = static_cast<Foo>(fooInt);
   // ...
}

Harap dicatat, enum Lastdimaksudkan untuk dilewati oleh iterasi. Dengan menggunakan Lastenum "palsu" ini , Anda tidak harus memperbarui kondisi terminating di dalam for loop ke enum "real" terakhir setiap kali Anda ingin menambahkan enum baru. Jika Anda ingin menambahkan lebih banyak enum nanti, cukup tambahkan sebelum Terakhir. Loop dalam contoh ini masih akan berfungsi.

Tentu saja, ini rusak jika nilai enum ditentukan:

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

Ini menggambarkan bahwa enum tidak dimaksudkan untuk diulangi. Cara khas untuk menangani enum adalah menggunakannya dalam pernyataan pergantian.

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

Jika Anda benar-benar ingin menghitung, masukkan nilai enum dalam vektor dan ulangi. Ini akan menangani dengan baik nilai enum yang ditentukan juga.

andreas buykx
sumber
13
Perhatikan bahwa, pada bagian pertama dari contoh, jika Anda ingin menggunakan 'i' sebagai Foo enum dan bukan int, Anda perlu melakukan pelepasan statis seperti: static_cast <Foo> (i)
Clayton
5
Anda juga melewatkan Terakhir di loop. Harus <= Terakhir
Tony
20
@Tony Last dimaksudkan untuk dilewati. Jika Anda ingin menambahkan lebih banyak enums nanti, tambahkan sebelum Last ... loop pada contoh pertama masih berfungsi. Dengan menggunakan enum "palsu" Terakhir, Anda tidak harus memperbarui kondisi terminating Anda dalam loop untuk enum "nyata" terakhir setiap kali Anda ingin menambahkan enum baru.
timidpueo
Kecuali sekarang Anda telah mengalokasikan memori saat enum, asalkan tidak diindeks dan benar-benar kontinu, dapat melakukan tugas itu tanpa mengalokasikan memori.
Awan
1
Perhatikan bahwa untuk definisi enum ini aman untuk pembaruan, orang harus menentukan nilai UNKNOWN = 0. Selain itu, saya akan menyarankan untuk hanya menjatuhkan defaultcase ketika beralih nilai enum karena mungkin menyembunyikan kasus-kasus di mana penanganan nilai-nilai dilupakan sampai runtime. Sebagai gantinya, seseorang harus meng-hardcode semua nilai dan menggunakan UNKNOWNbidang untuk mendeteksi ketidaksesuaian.
Benjamin Bannier
53
#include <iostream>
#include <algorithm>

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;
}
zdf
sumber
Terima kasih! Perhatikan bahwa jika Anda memotong file / kelas dan jika kompatibilitas MS memberi Anda masalah dengan konstanta non-integer yang dinyatakan header, ini membantu di bawah kompiler saya untuk secara eksplisit menempatkan ukuran dalam jenis di header: static const Type All[3];dan kemudian saya bisa untuk menginisialisasi dalam sumber: const MyEnum::Type MyEnum::All[3] = { a, b, c }; Sebelum melakukan itu, saya mendapatkan Error in range-based for...kesalahan menjengkelkan (karena array memiliki ukuran yang tidak diketahui). Menemukan ini berkat jawaban terkait
bijak
1
Versi array sangat bersahabat dengan copy paste. Selain jawaban yang paling memuaskan, "TIDAK" atau "hanya untuk urutan". Bahkan mungkin ramah makro.
Paulo Neves
1
ini mungkin merupakan solusi yang baik untuk enum dengan jumlah item yang sedikit, tetapi untuk enum dengan jumlah item yang besar itu tidak boleh cocok.
kato2
20

Jika enum Anda mulai dengan 0 dan kenaikan selalu 1.

enum enumType 
{ 
    A = 0,
    B,
    C,
    enumTypeEnd
};

for(int i=0; i<enumTypeEnd; i++)
{
   enumType eCurrent = (enumType) i;            
}

Jika tidak, saya kira satu-satunya sebabnya adalah membuat sesuatu seperti

vector<enumType> vEnums;

tambahkan item, dan gunakan iterators normal ....

João Augusto
sumber
19

Dengan c ++ 11, sebenarnya ada alternatif: menulis iterator kustom templatized sederhana.

mari kita asumsikan enum Anda

enum class foo {
  one,
  two,
  three
};

Kode generik ini akan melakukan triknya, cukup efisien - tempatkan di header generik, itu akan membantu Anda untuk setiap enum yang mungkin perlu Anda ulangi:

#include <type_traits>
template < typename C, C beginVal, C endVal>
class Iterator {
  typedef typename std::underlying_type<C>::type val_t;
  int val;
public:
  Iterator(const C & f) : val(static_cast<val_t>(f)) {}
  Iterator() : val(static_cast<val_t>(beginVal)) {}
  Iterator operator++() {
    ++val;
    return *this;
  }
  C operator*() { return static_cast<C>(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; }
};

Anda harus mengkhususkannya

typedef Iterator<foo, foo::one, foo::three> fooIterator;

Dan kemudian Anda bisa beralih menggunakan range-for

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

Asumsi bahwa Anda tidak memiliki celah di enum Anda masih benar; tidak ada asumsi pada jumlah bit yang sebenarnya diperlukan untuk menyimpan nilai enum (terima kasih kepada std :: underlying_type)

Francesco Chemolli
sumber
1
@ lepe? Anda hanya membuat typedef yang berbeda untuk enum yang berbeda.
Andrew Lazarus
2
@ Lepe Itu seperti mengatakan itu std::vectortidak generik karena std::vector<foo>terikat foo.
Kyle Strand
1
typedef Iterator<color, color::green, color::red> colorIterator;Pastikan Anda memahami cara kerja Instansiasi template.
Andrew Lazarus
2
Oh, saya melihat masalah - foo operator*() { ...seharusnya C operator*() { ....
Kyle Strand
1
@KyleStrand: Anda mengerti! itu masuk akal sekarang. Haruskah kode diperbarui? Terima kasih semuanya atas penjelasan Anda.
lepe
16

terlalu rumit solusi ini, saya suka itu:

enum NodePosition { Primary = 0, Secondary = 1, Tertiary = 2, Quaternary = 3};

const NodePosition NodePositionVector[] = { Primary, Secondary, Tertiary, Quaternary };

for (NodePosition pos : NodePositionVector) {
...
}
Enzojz
sumber
Saya tidak tahu mengapa ini diturunkan. Ini solusi yang masuk akal.
Paul Brannan
11
Saya berharap itu karena entri perlu dipertahankan di dua tempat.
Semut
Apakah C ++ mengizinkan for (NodePosition pos : NodePositionVector)sintaks? Sejauh yang saya tahu ini adalah sintaks Java, dan Anda akan memerlukan iterator di C ++ untuk melakukan sesuatu yang setara.
thegreatjedi
3
@thegreatjedi Sejak C ++ 11 Anda dapat, bahkan lebih sederhana: untuk (pos otomatis: NodePositionVector) {..}
Enzojz
@ thegreatjedi Akan lebih cepat untuk mencari, atau bahkan menyusun program pengujian, daripada mengajukan pertanyaan itu. Tapi ya, karena C ++ 11 itu adalah sintaks C ++ yang benar-benar valid, yang diterjemahkan oleh kompiler ke kode yang setara (dan jauh lebih verbose / kurang abstrak), biasanya melalui iterator; lihat Preferensi Cp . Dan, seperti kata Enzojz, C ++ 11 juga ditambahkan auto, jadi Anda tidak harus mendeklarasikan jenis elemen secara eksplisit, kecuali jika Anda (A) perlu menggunakan operator konversi atau (B) tidak suka autokarena suatu alasan . Sebagian besar forpengguna rentang menggunakan autoAFAICT
underscore_d
9

Saya sering melakukannya seperti itu

    enum EMyEnum
    {
        E_First,
        E_Orange = E_First,
        E_Green,
        E_White,
        E_Blue,
        E_Last
    }

    for (EMyEnum i = E_First; i < E_Last; i = EMyEnum(i + 1))
    {}

atau jika tidak berturut-turut, tetapi dengan langkah reguler (mis. bendera bit)

    enum EAnimalCaps
    {
        E_First,
        E_None    = E_First,
        E_CanFly  = 0x1,
        E_CanWalk = 0x2
        E_CanSwim = 0x4,
        E_Last
    }

    class MyAnimal
    {
       EAnimalCaps m_Caps;
    }

    class Frog
    {
        Frog() : 
            m_Caps(EAnimalCaps(E_CanWalk | E_CanSwim))
        {}
    }

    for (EAnimalCaps= E_First; i < E_Last; i = EAnimalCaps(i << 1))
    {}
Niki
sumber
tapi, apa gunanya mencetak nilai sedikit?
Anu
1
Untuk menggunakan enum untuk membuat bitmask. mis., gabungkan beberapa opsi dalam variabel tunggal, kemudian gunakan FOR untuk menguji setiap opsi. Memperbaiki posting saya dengan contoh yang lebih baik.
Niki
Saya masih belum bisa menggunakannya (& pos Anda masih menunjukkan contoh lama)! Menggunakan enum sebagai bitmasks sangat membantu, tetapi tidak dapat menghubungkan titik-titik! bisa tolong jelaskan sedikit dalam contoh Anda secara detail, Anda dapat memasukkan kode tambahan juga.
Anu
@anu Maaf tidak melihat komentar Anda. Menambahkan kelas Frog sebagai contoh bitmask
Niki
8

Anda tidak bisa dengan enum. Mungkin enum bukan yang paling cocok untuk situasi Anda.

Sebuah konvensi umum adalah untuk memberi nama nilai enum terakhir seperti MAX dan menggunakannya untuk mengontrol loop menggunakan int.

Corey Trager
sumber
Ada beberapa contoh di sini yang menunjukkan yang sebaliknya. Saya sendiri pernyataan Anda, Anda bertentangan dengan diri sendiri (baris kedua).
Niki
6

Sesuatu yang belum tercakup dalam jawaban lain = jika Anda menggunakan enums C ++ 11 yang diketik dengan kuat, Anda tidak dapat menggunakan ++atau menggunakannya + int. Dalam hal ini, sedikit solusi berantakan diperlukan:

enum class myenumtype {
  MYENUM_FIRST,
  MYENUM_OTHER,
  MYENUM_LAST
}

for(myenumtype myenum = myenumtype::MYENUM_FIRST;
    myenum != myenumtype::MYENUM_LAST;
    myenum = static_cast<myenumtype>(static_cast<int>(myenum) + 1)) {

  do_whatever(myenum)

}
Kerusuhan
sumber
3
... tapi C ++ 11 memperkenalkan rentang yang berdasarkan yang ditunjukkan pada jawaban lain. :-)
sage
5

Anda dapat mencoba dan mendefinisikan makro berikut:

#define for_range(_type, _param, _A1, _B1) for (bool _ok = true; _ok;)\
for (_type _start = _A1, _finish = _B1; _ok;)\
    for (int _step = 2*(((int)_finish)>(int)_start)-1;_ok;)\
         for (_type _param = _start; _ok ; \
 (_param != _finish ? \
           _param = static_cast<_type>(((int)_param)+_step) : _ok = false))

Sekarang Anda dapat menggunakannya:

enum Count { zero, one, two, three }; 

    for_range (Count, c, zero, three)
    {
        cout << "forward: " << c << endl;
    }

Ini dapat digunakan untuk beralih mundur dan maju melalui unsigned, integer, enums dan chars:

for_range (unsigned, i, 10,0)
{
    cout << "backwards i: " << i << endl;
}


for_range (char, c, 'z','a')
{
    cout << c << endl;
}

Meskipun definisi canggung itu dioptimalkan dengan sangat baik. Saya melihat disassembler di VC ++. Kode ini sangat efisien. Jangan menunda tetapi ketiganya untuk pernyataan: kompiler hanya akan menghasilkan satu loop setelah optimasi! Anda bahkan dapat mendefinisikan loop tertutup:

unsigned p[4][5];

for_range (Count, i, zero,three)
    for_range(unsigned int, j, 4, 0)
    {   
        p[i][j] = static_cast<unsigned>(i)+j;
    }

Anda jelas tidak dapat mengulangi melalui tipe yang disebutkan dengan kesenjangan.

Mikhail Semenov
sumber
1
Itu hack yang luar biasa! Meskipun lebih cocok untuk C daripada untuk C ++, bisa dikatakan.
einpoklum
3
_A1bukan nama yang diizinkan, ini adalah garis bawah utama dengan huruf kapital berikut.
Martin Ueding
3

Anda juga dapat membebani operator kenaikan / penurunan untuk tipe enumerasi Anda.

JohnMcG
sumber
1
Anda tidak dapat membebani operator apa pun pada tipe enumerasi C atau C ++. Kecuali jika Anda membuat struct / kelas yang meniru enumerasi nilai.
Trevor Hickey
2
C ++ memungkinkan operator kelebihan muatan pada enum. Lihat stackoverflow.com/questions/2571456/… .
Arch D. Robison
Kelebihan kenaikan / penurunan mengharuskan Anda membuat keputusan tentang apa yang harus dilakukan ketika ada luapan
Eponim
3

Dengan asumsi bahwa enum diberi nomor secara berurutan adalah rawan kesalahan. Selain itu, Anda mungkin ingin beralih hanya menggunakan enumerator terpilih. Jika bagian itu kecil, mengulanginya secara eksplisit mungkin merupakan pilihan yang elegan:

enum Item { Man, Wolf, Goat, Cabbage }; // or enum class

for (auto item : {Wolf, Goat, Cabbage}) { // or Item::Wolf, ...
    // ...
}
marski
sumber
Ini adalah opsi yang bagus menurut saya. Harus menjadi bagian dari spesifikasi C ++ yang lebih baru daripada yang saya gunakan ketika saya mengajukan pertanyaan yang saya duga?
Adam
Iya. Itu berulang melalui std :: initializer_list <Item>. tautan .
marski
2

Jika Anda tidak ingin mencemari Anda enum dengan item COUNT akhir (karena mungkin jika Anda juga menggunakan enum dalam sebuah saklar, maka kompiler akan memperingatkan Anda tentang kasus COUNT yang hilang :), Anda dapat melakukan ini:

enum Colour {Red, Green, Blue};
const Colour LastColour = Blue;

Colour co(0);
while (true) {
  // do stuff with co
  // ...
  if (co == LastColour) break;
  co = Colour(co+1);
}
Niels Holst
sumber
2

Inilah solusi lain yang hanya berfungsi untuk enum yang berdekatan. Ini memberikan iterasi yang diharapkan, kecuali untuk keburukan dalam kenaikan, yang merupakan tempatnya, karena itulah yang rusak di C ++.

enum Bar {
    One = 1,
    Two,
    Three,
    End_Bar // Marker for end of enum; 
};

for (Bar foo = One; foo < End_Bar; foo = Bar(foo + 1))
{
    // ...
}
Ethan Bradford
sumber
1
Penambahan bisa disingkat menjadi foo = Bar(foo + 1).
HolyBlackCat
Terima kasih, HolyBlackCat, saya telah memasukkan saran luar biasa Anda! Saya juga memperhatikan bahwa Riot memiliki cukup banyak solusi yang sama, tetapi sesuai dengan pengetikan yang kuat (dan karenanya lebih bertele-tele).
Ethan Bradford
2
enum class A {
    a0=0, a3=3, a4=4
};
constexpr std::array<A, 3> ALL_A {A::a0, A::a3, A::a4}; // constexpr is important here

for(A a: ALL_A) {
  if(a==A::a0 || a==A::a4) std::cout << static_cast<int>(a);
}

SEBUAH constexpr std::array dapat mengulang bahkan enum non-sekuensial tanpa array yang dipakai oleh kompiler. Ini tergantung pada hal-hal seperti heuristik optimisasi kompiler dan apakah Anda mengambil alamat array.

Dalam percobaan saya, saya menemukan bahwa g++9,1 dengan -O3akan mengoptimalkan array di atas jika ada 2 nilai non-sekuensial atau beberapa nilai sekuensial (saya menguji hingga 6). Tetapi ini hanya berlaku jika Anda memiliki ifpernyataan. (Saya mencoba pernyataan yang membandingkan nilai integer lebih besar dari semua elemen dalam array berurutan dan itu menggarisbawahi iterasi meskipun tidak ada yang dikecualikan, tetapi ketika saya meninggalkan pernyataan if, nilai-nilai itu dimasukkan ke dalam memori.) nilai dari enum non-sekuensial dalam [satu kasus | https://godbolt.org/z/XuGtoc] . Saya menduga perilaku aneh ini adalah karena heuristik yang mendalam berkaitan dengan cache dan prediksi cabang.

Berikut ini tautan ke tes iterasi sederhana di godbolt yang menunjukkan bahwa array tidak selalu dapat dipakai.

Harga dari teknik ini adalah menulis elemen enum dua kali dan menjaga kedua daftar tetap sinkron.

Eponim
sumber
Saya suka semantik rentang-seperti-untuk-loop sederhana dan saya pikir itu akan berkembang bahkan itulah sebabnya saya suka solusi ini.
rtischer8277
2

Dalam buku bahasa pemrograman C ++ dari Bjarne Stroustrup, Anda dapat membaca bahwa ia mengusulkan untuk membebani buku operator++khusus Anda enum. enumapakah tipe yang ditentukan pengguna dan operator kelebihan beban ada dalam bahasa untuk situasi khusus ini.

Anda dapat membuat kode berikut:

#include <iostream>
enum class Colors{red, green, blue};
Colors& operator++(Colors &c, int)
{
     switch(c)
     {
           case Colors::red:
               return c=Colors::green;
           case Colors::green:
               return c=Colors::blue;
           case Colors::blue:
               return c=Colors::red; // managing overflow
           default:
               throw std::exception(); // or do anything else to manage the error...
     }
}

int main()
{
    Colors c = Colors::red;
    // casting in int just for convenience of output. 
    std::cout << (int)c++ << std::endl;
    std::cout << (int)c++ << std::endl;
    std::cout << (int)c++ << std::endl;
    std::cout << (int)c++ << std::endl;
    std::cout << (int)c++ << std::endl;
    return 0;
}

kode uji: http://cpp.sh/357gb

Pikiran yang saya gunakan enum class. Kode berfungsi dengan baik enumjuga. Tapi saya lebih suka enum classkarena mereka diketik dengan kuat dan dapat mencegah kita melakukan kesalahan pada waktu kompilasi.

LAL
sumber
Downvote dilakukan pada pos ini. Ada alasan mengapa itu tidak akan menjawab pertanyaan?
LAL
Alasannya mungkin karena ini adalah solusi yang mengerikan secara arsitektur: itu memaksa Anda untuk menulis logika global yang dimaksudkan untuk diikat ke komponen tertentu (enumerasi Anda), apalagi jika enumerasi Anda berubah karena alasan apa pun Anda terpaksa mengedit + Anda. + operator juga, sebagai pendekatan yang tidak berkelanjutan untuk proyek skala menengah-besar, itu tidak mengherankan itu berasal dari rekomendasi Bjarne Stroustrup, kembali pada hari-hari arsitektur perangkat lunak seperti fiksi ilmiah
Manjia
Pertanyaan awal adalah tentang memiliki operator ke enum. Itu bukan pertanyaan arsitektur. Saya tidak percaya bahwa pada 2013 C ++ adalah fiksi ilmiah.
LAL
1

Untuk kompiler MS:

#define inc_enum(i) ((decltype(i)) ((int)i + 1))

enum enumtype { one, two, three, count};
for(enumtype i = one; i < count; i = inc_enum(i))
{ 
    dostuff(i); 
}

Catatan: ini jauh lebih sedikit kode daripada jawaban iterator kustom templatized sederhana.

Anda bisa membuatnya bekerja dengan GCC dengan menggunakan typeofalih-alih decltype, tetapi saya tidak memiliki kompiler yang berguna saat ini untuk memastikan kompilasi.

pengguna2407277
sumber
Ini ditulis ~ 5 tahun setelah decltypemenjadi standar C ++, jadi sebaiknya Anda tidak merekomendasikan yang sudah ketinggalan zaman typeofdari GCC kuno. Menangani GCC baru- decltypebaru ini saja. Ada masalah lain: gips C-style tidak disarankan, & makro lebih buruk. Fitur C ++ yang tepat dapat memberikan fungsionalitas generik yang sama. Ini akan lebih baik ditulis ulang untuk menggunakan static_cast& fungsi template: template <typename T> auto inc_enum(T const t) { return static_cast<T>(static cast<int>(t) + 1); }. Dan gips tidak diperlukan untuk non- enum class. Atau, operator dapat kelebihan beban per enumjenis (TIL)
underscore_d
1
typedef enum{
    first = 2,
    second = 6,
    third = 17
}MyEnum;

static const int enumItems[] = {
    first,
    second,
    third
}

static const int EnumLength = sizeof(enumItems) / sizeof(int);

for(int i = 0; i < EnumLength; i++){
    //Do something with enumItems[i]
}
Justin Moloney
sumber
Solusi ini akan membuat variabel statis yang tidak perlu dalam memori sementara tujuan enum adalah hanya untuk membuat 'topeng' ke konstanta yang digarisbawahi
TheArquitect
Kecuali diubah menjadiconstexpr static const int enumItems[]
Mohammad Kanan
0

C ++ tidak memiliki introspeksi, jadi Anda tidak dapat menentukan hal seperti ini saat dijalankan.

kͩeͣmͮpͥ ͩ
sumber
1
Bisakah Anda menjelaskan kepada saya mengapa "introspeksi" diperlukan untuk beralih pada enum?
Jonathan Mee
Mungkin istilahnya Refleksi ?
kͩeͣmͮpͥ ͩ
2
Saya mencoba mengatakan 2 hal: 1) Per banyak jawaban lain, C ++ dapat menyelesaikannya, jadi jika Anda ingin mengatakannya tidak bisa, tautan atau klarifikasi lebih lanjut diperlukan. 2) Dalam bentuk saat ini, ini yang terbaik adalah komentar, tentu bukan jawaban.
Jonathan Mee
Turunkan jawaban saya - saya pikir Anda lebih dari membenarkannya
kͩeͣmͮpͥ ͩ
1
Saya akan menjejalkan lagi dalam 2 komentar: 1) Saya tidak downvote karena saya menemukan bahwa menerima downvote mendemotivasi partisipasi situs, saya menemukan kontraproduktif 2) Saya masih tidak mengerti apa yang Anda katakan tetapi kedengarannya seperti Anda memahami sesuatu yang saya tidak tahu dalam hal ini saya lebih suka Anda menjelaskan daripada menghapus jawaban yang downvoted.
Jonathan Mee
0

Jika Anda tahu bahwa nilai enum berurutan, misalnya Qt: Key enum, Anda bisa:

Qt::Key shortcut_key = Qt::Key_0;
for (int idx = 0; etc...) {
    ....
    if (shortcut_key <= Qt::Key_9) {
        fileMenu->addAction("abc", this, SLOT(onNewTab()),
                            QKeySequence(Qt::CTRL + shortcut_key));
        shortcut_key = (Qt::Key) (shortcut_key + 1);
    }
}

Ini berfungsi seperti yang diharapkan.

krossen
sumber
-1

Buat saja array int dan loop di atas array, tetapi buat elemen terakhir katakan -1 dan gunakan untuk kondisi keluar.

Jika enum adalah:

enum MyEnumType{Hay=12,Grass=42,Beer=39};

lalu buat array:

int Array[] = {Hay,Grass,Beer,-1};

for (int h = 0; Array[h] != -1; h++){
  doStuff( (MyEnumType) Array[h] );
}

Ini tidak rusak tidak peduli ints dalam representasi selama -1 cek tidak bertabrakan dengan salah satu elemen saja.

pembaca matematika
sumber