Bir enum üzerinde nasıl tekrar edebilirim?


304

Sadece ++ veya + = gibi bir numarada standart matematik operatörleri kullanamayacağınızı fark ettim

Peki bir C ++ numaralandırma tüm değerleri yineleme en iyi yolu nedir?


2
Birçok yaklaşımdan biri: Enum Sadece Yetmediğinde: C ++ için Numaralandırma Sınıfları . Ve daha kapsüllenmiş bir şey istiyorsanız, bu yaklaşımı James Kanze'den deneyin .
Don Wakefield

Bağlantılı öğelerin bazı ilginç yanıtları var.
Tony

Bu cevaplar, intyeterince büyük olmayan sorunu kapsamıyor gibi görünmüyor ! ( [C++03: 7.2/5])
Yörüngedeki Hafiflik Yarışları

İlginçtir ki, operator++numaralandırmalarda tanımlayabilirsiniz ; ancak, bunu yapabilirsiniz for(Enum_E e = (Enum_E)0; e < ENUM_COUNT; e++). Eğer döküm zorunda Not 0için Enum_Eçeteleler üzerinde C ++ yasakladığı atama operatörleri çünkü.
weberc2

Enum değerlerinden oluşan bir std :: initializer_list değişmezi yayabilen sizeof'in çalışma biçimine benzer bir derleme zamanı operatörü olsaydı, bir çözümümüz olurdu ve herhangi bir çalışma zamanı ek yükü içermezdik.
jbruni

Yanıtlar:


263

Tipik yolu aşağıdaki gibidir:

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

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

Lütfen not edin, numaralandırma Lastyinelemeyle atlanmalıdır. Bu "sahte" Lastnumaralandırmayı kullanarak , for döngüsünde sonlandırma koşulunuzu her "yeni " numara eklemek istediğinizde son "gerçek" numaraya güncellemeniz gerekmez. Daha sonra başka numaralar eklemek istiyorsanız, bunları Son'dan önce ekleyin. Bu örnekteki döngü yine de çalışır.

Tabii ki, enum değerleri belirtilirse bozulur:

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

Bu, bir enumun gerçekten yinelemek anlamına gelmediğini gösterir. Bir enum ile baş etmenin tipik yolu, bir switch deyiminde kullanmaktır.

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

Gerçekten numaralandırmak istiyorsanız, bir vektördeki enum değerlerini doldurun ve bunun üzerinde tekrarlayın. Bu, belirtilen numaralandırma değerleriyle de uygun şekilde ilgilenecektir.


13
Örneğin ilk bölümünde, 'i' yi bir int olarak değil, bir Foo enum olarak kullanmak istiyorsanız, statik olarak yayınlamanız gerekeceğini unutmayın: static_cast <Foo> (i)
Clayton

5
Ayrıca döngüdeki Son'u atlıyorsunuz. <= Son olmalı
Tony

20
@Tony Last, atlanacak. Daha sonra daha fazla numaralandırma eklemek isterseniz, bunları Son ... 'dan önce ekleyin. İlk örnekteki döngü yine de çalışır. Bir "sahte" Son numaralandırma kullanarak, for döngüsünde sonlandırma koşulunuzu her yeni numara eklemek istediğinizde son "gerçek" numaraya güncellemeniz gerekmez.
timidpueo

Şimdi, sıfırla endeksli ve kesinlikle sürekli olması koşuluyla, bir numaralandırma bellek ayırmadan bu görevi gerçekleştirebiliyorsa, aslında bellek tahsis ettiniz.
Bulut

1
Bu numaralandırma tanımının güncellemeler için güvenli olması için bir değer tanımlaması gerektiğini unutmayın UNKNOWN = 0. Ayrıca, defaultdeğerlerin işlenmesine çalışma zamanına kadar unutulduğu vakaları gizleyebileceğinden, numaralandırma değerlerini değiştirirken davayı bırakmanızı öneririm . Bunun yerine kişi tüm değerleri kodlamalı ve UNKNOWNalanı uyumsuzlukları tespit etmek için kullanmalıdır .
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;
}

Teşekkürler! Sen geçiş dosyaları / sınıfları ve MS uyumluluğu başlık ilan tamsayı olmayan sabitleri ile sorunların neler verip vermediğini, açıkça benim derleyici altında olur başlığındaki tip boyutunu koyarsanız Not olun: static const Type All[3];o zaman ben açabiliyorum Kaynakta başlatmak için: const MyEnum::Type MyEnum::All[3] = { a, b, c }; Bunu yapmadan önce, iğrenç Error in range-based for...hatalar alıyordum (çünkü dizi bilinmeyen bir boyuta sahipti). İlgili bir cevap
adaçayı

1
Dizi sürümü kopya yapıştır çok kolay. Bunun dışında en tatmin edici cevap, "HAYIR" veya "sadece sıralı olarak". Muhtemelen makro dostu bile.
Paulo Neves

1
bu, az sayıda öğe içeren numaralandırmalar için iyi bir çözüm olabilir, ancak çok sayıda öğe içeren numaralandırmalar için uygun olmamalıdır.
kato2

20

Numaralandırmanız 0 ile başlıyorsa ve artış her zaman 1 ise.

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

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

Değilse, sanırım tek neden bir şey yaratmaktır.

vector<enumType> vEnums;

öğeleri ekleyin ve normal yineleyiciler kullanın ....


19

C ++ 11 ile, aslında bir alternatif var: basit bir templatized özel yineleyici yazma.

diyelim ki sıralamanız

enum class foo {
  one,
  two,
  three
};

Bu genel kod, hileyi oldukça verimli bir şekilde yapacak - genel bir başlığa yerleştirin, tekrarlamanız gereken herhangi bir numaralandırma için size hizmet edecektir:

#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; }
};

Uzmanlaşmanız gerekecek

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

Ve sonra range-for

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

Sayımınızda boşluk olmadığına dair varsayım hala doğrudur; enum değerini depolamak için gerçekten gerekli olan bit sayısı hakkında herhangi bir varsayım yoktur (std :: underlying_type sayesinde)


1
@lepe? Sadece farklı bir numaralandırma için farklı bir typedef yaparsınız.
Andrew Lazarus

2
@lepe Bu std::vector, jenerik olmadığını söylemeye benziyor , çünkü std::vector<foo>bağlı foo.
Kyle Strand

1
typedef Iterator<color, color::green, color::red> colorIterator;Şablon örneklemelerinin nasıl çalıştığını anladığınızdan emin olun.
Andrew Lazarus

2
Oh, sorunu görüyorum - foo operator*() { ...olmalı C operator*() { ....
Kyle Strand

1
@KyleStrand: Anladın! bu artık tamamen mantıklı. Kod güncellenmeli mi? Açıklamalarınız için herkese teşekkürler.
lepe

16

Bu çözüm çok karmaşık, bunu gibi:

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

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

for (NodePosition pos : NodePositionVector) {
...
}

Bunun neden reddedildiğini bilmiyorum. Makul bir çözüm.
Paul Brannan

11
Ben girişleri iki yerde muhafaza edilmesi gerekiyordu çünkü oldu.
Karınca

C ++ for (NodePosition pos : NodePositionVector)sözdizimine izin veriyor mu? Bildiğim kadarıyla bu Java sözdizimi ve eşdeğer bir şey yapmak için C ++ yineleyicilerine ihtiyacınız olacak.
thegreatjedi

3
@thegreatjedi C ++ 11'den bu yana, daha da basit yapabilirsiniz: (auto pos: NodePositionVector) için {..}
Enzojz

@thegreatjedi Bu soruyu sormaktan ziyade bir test programı aramak veya hatta derlemek daha hızlı olurdu. Ancak evet, C ++ 11 olduğundan, derleyicinin genellikle yineleyiciler aracılığıyla eşdeğer (ve çok daha ayrıntılı / daha az soyutlayıcı) koda çevirdiği mükemmel geçerli C ++ sözdizimi; cppreference bakın . Ve, Enzojz'un dediği gibi, C ++ 11 de eklendi auto, bu nedenle (A) bir dönüşüm operatörü kullanmanız veya (B) autoherhangi bir nedenden dolayı beğenmediğiniz sürece, öğelerin türünü açıkça beyan etmek zorunda değilsiniz. . Çoğu aralık forkullanıcısı AFAICT kullanırauto
underscore_d

9

Sık sık böyle yaparım

    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))
    {}

veya ardışık değilse, ancak düzenli adımlarla (örn. bit bayrakları)

    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))
    {}

ancak, değerleri bilge olarak basmanın faydası nedir?
Anu

1
Bitmask'ler oluşturmak için numaralandırmaları kullanmak. örneğin, çeşitli seçenekleri tek bir değişkente birleştirin, ardından her seçeneği test etmek için FOR'u kullanın. Yayımım daha iyi bir örnekle düzeltildi.
Niki

Hala kullanamıyorum (ve yayınınız hala eski örneği gösteriyor)! Enum'u bitmask olarak kullanmak gerçekten yararlıdır, ancak noktaları birleştiremedi! lütfen örnekte biraz ayrıntılı olarak açıklayabilir misiniz, ek kodu da koyabilirsiniz.
Anu

@anu Üzgünüz, yorumunuzu görmediniz. Bitmask örneği olarak Frog sınıfı eklendi
Niki

8

Bir numaralandırma ile yapamazsınız. Belki bir enum durumunuza en uygun değildir.

Ortak bir kural, son numaralandırma değerini MAX gibi bir ad olarak adlandırmak ve bunu bir int kullanarak bir döngüyü kontrol etmek için kullanmaktır.


Burada bunun tersini gösteren birkaç örnek var. Ben kendi ifadenle, kendinle çelişiyorsun (ikinci satır).
Niki

6

Sen kullanamazsınız kesinlikle yazılı C ++ 11 çeteleler kullanıyorsanız = diğer yanıtlar kaplı olan sey ++veya + intüzerlerinde. Bu durumda, biraz daha karışık bir çözüm gereklidir:

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)

}

3
... ancak C ++ 11, diğer cevaplarda gösterilen buna dayalı aralığı sunar. :-)
adaçayı

5

Aşağıdaki makroyu deneyebilir ve tanımlayabilirsiniz:

#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))

Şimdi kullanabilirsiniz:

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

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

İmzasız, tamsayılar, numaralar ve karakterlerle geriye ve ileriye doğru yineleme yapmak için kullanılabilir:

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


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

Garip tanımına rağmen çok iyi optimize edildi. VC ++ 'daki sökücüye baktım. Kod son derece verimlidir. Bırakmayın ama üç ifade için: derleyici optimizasyondan sonra sadece bir döngü üretecektir! Ekteki döngüleri bile tanımlayabilirsiniz:

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;
    }

Açıkçası, boşluklu numaralandırılmış türler arasında yineleme yapamazsınız.


1
Bu harika bir hack! C için C ++ 'dan daha uygun olmasına rağmen, söylenebilir.
einpoklum

3
_A1izin verilen bir ad değil, aşağıdaki büyük harfle önde gelen bir alt çizgidir.
Martin Ueding

3

Numaralandırılmış türünüz için artış / azalma operatörlerini de aşırı yükleyebilirsiniz.


1
C veya C ++ numaralandırılmış türlerde herhangi bir operatörü aşırı yükleyemezsiniz. Değerlerin numaralandırılmasını taklit eden bir yapı / sınıf yaratmadığınız sürece.
Trevor Hickey

2
C ++, numaralandırmalarda operatörlerin aşırı yüklenmesini sağlar. Bkz. Stackoverflow.com/questions/2571456/… .
Arch D. Robison

Artış / azalışın aşırı
yüklenmesi

3

Numaralandırmanın sırayla numaralandırıldığı varsayılarak hataya açıktır. Ayrıca, yalnızca seçilen numaralandırıcılar üzerinde yineleme yapmak isteyebilirsiniz. Bu altküme küçükse, açıkça döngü yapmak zarif bir seçim olabilir:

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

for (auto item : {Wolf, Goat, Cabbage}) { // or Item::Wolf, ...
    // ...
}

Bu bence güzel bir seçenek. Tahmin ettiğim soruyu sorduğumda kullandığımdan daha yeni bir C ++ spesifikasyonunun parçası olmalı mı?
Adam

Evet. Bir std :: initializer_list <Item> üzerinden yinelenir. bağlantısını tıklayın .
marski

2

Eğer numaralandırmayı son bir COUNT öğeyle kirletmek istemiyorsanız (belki de numaralandırmayı bir anahtarda da kullanırsanız, derleyici sizi eksik COUNT durumdan haberdar edecektir :), bunu yapabilirsiniz:

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);
}

2

İşte sadece bitişik numaralandırmalar için çalışan başka bir çözüm. C ++ 'da kırılan şey olduğu için, ait olduğu yerde olan artıştaki çirkinlik dışında beklenen yinelemeyi verir.

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

for (Bar foo = One; foo < End_Bar; foo = Bar(foo + 1))
{
    // ...
}

1
Artış kısaltılabilir foo = Bar(foo + 1).
HolyBlackCat

Teşekkürler HolyBlackCat, mükemmel önerinizi ekledim! Ayrıca Riot'un hemen hemen aynı çözüme sahip olduğunu, ancak güçlü yazımla (ve dolayısıyla daha ayrıntılı) uyumlu olduğunu fark ettim.
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);
}

A constexpr std::array, dizi derleyici tarafından başlatılmadan sıralı olmayan numaralandırmaları bile yineleyebilir. Bu, derleyicinin optimizasyon buluşsal yöntemlerine ve dizinin adresini alıp almadığınıza bağlıdır.

Deneylerimde, 2 ardışık değer veya oldukça az ardışık değer varsa g++9.1 ile -O3yukarıdaki diziyi optimize edeceğini buldum (6'ya kadar test ettim). Ama bunu sadece birif . (Sıralı bir dizideki tüm öğelerden daha büyük bir tamsayı değeri karşılaştıran bir ifade denedim ve hiçbiri hariç tutulmamasına rağmen yinelemeyi inline etti, ancak if ifadesini bıraktığımda değerler belleğe konuldu.) vakada sıralı olmayan bir numaradan alınan değerler [bir | https://godbolt.org/z/XuGtoc] . Bu garip davranışın önbellekler ve dal tahmini ile ilgili derin sezgisel taramalardan kaynaklandığından şüpheleniyorum.

Burada bir dizinin her zaman somutlaştırılmadığını gösteren godbolt üzerinde basit bir test yinelemesine bağlantı .

Bu tekniğin fiyatı, enum öğelerini iki kez yazmak ve iki listeyi senkronize tutmaktır.


Basit, döngü benzeri semantikleri severim ve daha da gelişeceğini düşünüyorum, bu yüzden bu çözümü seviyorum.
rtischer8277

2

Dil kitabı programlama Bjarne Stroustrup'un C ++ olarak, o aşırı öneren ki okuyun edebilirsiniz operator++senin özgü için enum.enumkullanıcı tanımlı türlerdir ve aşırı yükleme operatörü bu özel durumlar için dilde mevcuttur.

Aşağıdakileri kodlayabilirsiniz:

#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;
}

test kodu: http://cpp.sh/357gb

Dikkatli olun enum class. Kod enumda iyi çalışıyor . Ama ben enum classgüçlü yazıldığından ve derleme zamanında hata yapmamızı engelleyebileceğinden tercih ederim .


Bu yayında bir aşağı oy kullanıldı. Bunun soruya cevap vermemesinin bir nedeni var mı?
LAL

Bunun nedeni muhtemelen bunun mimari olarak korkunç bir çözüm olmasıdır: sizi belirli bir bileşene (numaralandırmanıza) bağlı küresel mantıksal mantık yazmaya zorlar, ayrıca numaralandırmanız herhangi bir nedenden dolayı zorla değiştirilirse + + operatör de, bir yaklaşım olarak herhangi bir orta-büyük ölçekli proje için sürdürülebilir değildir, yazılım mimarisinin bilim kurgu gibi olduğu günlerde Bjarne Stroustrup'un önerisinden gelmesi sürpriz değildir
11

Asıl soru operatörün bir enum. Mimari bir soru değildi. 2013 yılında C ++ 'ın bir bilim kurgu olduğuna inanmıyorum.
LAL

1

MS derleyicileri için:

#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); 
}

Not: Bu, basit templatized custom iterator cevabından çok daha az koddur.

Bunun typeofyerine kullanarak GCC ile çalışmak için alabilirsiniz decltype, ama şu anda derlemek emin olmak için o derleyici kullanışlı yok.


Bu decltypestandart C ++ olduktan ~ 5 yıl sonra yazılmıştır , bu yüzden typeofeski GCC'den eskimiş tavsiye etmemelisiniz . Son zamanlarda ortaya çıkan GCC decltypeiyi işliyor . Başka sorunlar da var: C tarzı dökümler önerilmez ve makrolar daha kötüdür. Uygun C ++ özellikleri aynı genel işlevselliği verebilir. Bu daha iyi kullanmak için yeniden olurdu static_cast& bir şablon işlevi: template <typename T> auto inc_enum(T const t) { return static_cast<T>(static cast<int>(t) + 1); }. Ve olmayanlar için yayınlar gerekmez enum class. Alternatif olarak, operatörler enumtip başına aşırı yüklenebilir (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]
}

Bu çözüm, bellekte gereksiz yere statik değişkenler yaratırken, numaralandırmanın amacı sadece satır içi sabitlere bir 'maske' oluşturmaktır
TheArquitect

Değiştirilmediconstexpr static const int enumItems[]
Mohammad Kanan

0

C ++ 'ın içgözlemi yoktur, bu nedenle çalışma zamanında bu tür şeyleri belirleyemezsiniz.


1
Bana bir enum üzerinde yineleme yapmak için neden "içgözlem" gerekli olduğunu açıklayabilir misiniz?
Jonathan Mee

Belki Terim Yansıtma ?
kͩeͣmͮpͥ ͩ

2
Ben 2 şey söylemeye çalışıyorum: 1) Diğer cevaplar başına C ++ bunu başarabilir, eğer bunu söyleyemezseniz, bir bağlantı veya daha fazla açıklama gereklidir. 2) Şu anki haliyle bu en iyi yorumdur, kesinlikle bir cevap değildir.
Jonathan Mee

Cevabımı küçümseyin - Sanırım haklı olmaktan daha fazlası
kͩeͣmͮpͥ ͩ

1
2 yorumda tekrar tıklayacağım: 1) Aşağı oy kullanmıyorum, çünkü bir aşağı oy almanın siteye katılımı zorladığını görüyorum, bunun karşı üretken olduğunu görüyorum 2) Hala ne söylemeye çalıştığını anlamıyorum ama kulağa benziyor bilmediğim bir şey anlıyorsun, bu durumda indirilmiş bir cevabı silmek yerine ayrıntılı bir şekilde tercih ederim.
Jonathan Mee

0

Numaralandırma değerlerinin sıralı olduğunu, örneğin Qt: Key enum olduğunu biliyorsanız, şunları yapabilirsiniz:

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);
    }
}

Beklendiği gibi çalışır.


-1

Sadece bir ints dizisi yapın ve dizi üzerinde döngü yapın, ancak son öğeyi -1 deyin ve çıkış koşulu için kullanın.

Enum ise:

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

sonra dizi oluşturun:

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

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

-1 kontrolü elbette unsurlardan biriyle çarpışmadığı sürece, gösterimdeki veriler ne olursa olsun bu bozulmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.