Làm thế nào tôi có thể lặp đi lặp lại một enum?


304

Tôi chỉ nhận thấy rằng bạn không thể sử dụng các toán tử toán học tiêu chuẩn trên một enum như ++ hoặc + =

Vì vậy, cách tốt nhất để lặp qua tất cả các giá trị trong một enum C ++ là gì?


2
Một trong nhiều cách tiếp cận: Khi enum Chỉ không đủ: Các lớp liệt kê cho C ++ . Và, nếu bạn muốn một cái gì đó được gói gọn hơn, hãy thử phương pháp này từ James Kanze.
Don Wakefield

Các mục liên kết có một số phản ứng thú vị.
Tony

Những câu trả lời này dường như không bao gồm vấn đề intcó thể không đủ lớn! ( [C++03: 7.2/5])
Các cuộc đua nhẹ nhàng trong quỹ đạo

Thật thú vị, bạn có thể định nghĩa operator++trên enums; Tuy nhiên, vì vậy bạn có thể làm for(Enum_E e = (Enum_E)0; e < ENUM_COUNT; e++). Lưu ý bạn phải cast 0để Enum_Evì các nhà khai thác C ++ cấm chuyển nhượng trên enums.
weberc2

Nếu có một toán tử thời gian biên dịch, tương tự như cách hoạt động của sizeof, có thể phát ra một std :: initizer_list bao gồm các giá trị của enum, chúng ta sẽ có một giải pháp và sẽ không liên quan đến bất kỳ thời gian chạy nào.
jbruni

Câu trả lời:


263

Cách điển hình như sau:

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

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

Xin lưu ý, enum Last có nghĩa là được bỏ qua bởi phép lặp. Sử dụng Lastenum "giả" này , bạn không phải cập nhật điều kiện kết thúc của mình trong vòng lặp for thành enum "thực" cuối cùng mỗi khi bạn muốn thêm một enum mới. Nếu bạn muốn thêm nhiều enums sau, chỉ cần thêm chúng trước Last. Vòng lặp trong ví dụ này vẫn sẽ hoạt động.

Tất nhiên, điều này bị phá vỡ nếu các giá trị enum được chỉ định:

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

Điều này minh họa rằng một enum không thực sự có nghĩa là lặp đi lặp lại. Cách điển hình để đối phó với một enum là sử dụng nó trong câu lệnh switch.

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

Nếu bạn thực sự muốn liệt kê, nhét các giá trị enum vào một vectơ và lặp lại trên đó. Điều này cũng sẽ giải quyết đúng với các giá trị enum được chỉ định.


13
Lưu ý rằng, trong phần đầu tiên của ví dụ, nếu bạn muốn sử dụng 'i' như một Foo enum chứ không phải int, bạn sẽ cần phải truyền tĩnh nó như: static_cast <Foo> (i)
Clayton

5
Ngoài ra, bạn đang bỏ qua Cuối cùng trong vòng lặp. Nên là <= Lần cuối
Tony

20
@Tony Cuối cùng có nghĩa là được bỏ qua. Nếu bạn muốn thêm nhiều enums sau, hãy thêm chúng trước Last ... vòng lặp trong ví dụ đầu tiên sẽ vẫn hoạt động. Bằng cách sử dụng enum cuối cùng "giả", bạn không phải cập nhật điều kiện kết thúc của mình trong vòng lặp for thành enum "thực" cuối cùng mỗi khi bạn muốn thêm một enum mới.
timidpueo

Ngoại trừ bây giờ bạn đã thực sự phân bổ bộ nhớ khi enum, miễn là nó không có chỉ mục và liên tục nghiêm ngặt, có thể thực hiện nhiệm vụ đó mà không cần phân bổ bộ nhớ.
Đám mây

1
Lưu ý rằng để định nghĩa enum này an toàn cho các cập nhật, ta nên xác định một giá trị UNKNOWN = 0. Ngoài ra, tôi sẽ đề nghị bỏ defaulttrường hợp này khi chuyển qua các giá trị enum vì nó có thể ẩn các trường hợp mà việc xử lý các giá trị bị lãng quên cho đến khi thực thi. Thay vào đó, người ta nên mã hóa tất cả các giá trị và sử dụng UNKNOWNtrường để phát hiện sự không tương thích.
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;
}

Cảm ơn! Lưu ý rằng nếu bạn đang file qua / classes và nếu MS khả năng tương thích là đem lại cho bạn các vấn đề với các hằng số không nguyên header-tuyên bố, nó giúp dưới trình biên dịch của tôi để dứt khoát đặt kích thước trong các loại trong tiêu đề: static const Type All[3];và sau đó tôi có thể để khởi tạo trong nguồn: const MyEnum::Type MyEnum::All[3] = { a, b, c }; Trước khi làm điều đó, tôi đã nhận được các Error in range-based for...lỗi đáng ghét (vì mảng có kích thước không xác định). Tìm ra điều này nhờ vào một câu trả lời có liên quan
hiền nhân

1
Phiên bản mảng rất thân thiện với bản sao dán. Câu trả lời thỏa đáng nhất bên cạnh đó, "KHÔNG" hoặc "chỉ dành cho tuần tự". Có lẽ là thân thiện vĩ mô ngay cả.
Paulo Neves

1
đây có thể là một giải pháp tốt cho các enum có số lượng vật phẩm ít, nhưng đối với các enum có số lượng vật phẩm lớn thì nó không phù hợp lắm.
kato2

20

Nếu enum của bạn bắt đầu bằng 0 và mức tăng luôn là 1.

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

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

Nếu không tôi đoán lý do duy nhất là tạo ra một cái gì đó như một

vector<enumType> vEnums;

thêm các mục và sử dụng các trình vòng lặp bình thường ....


19

Với c ++ 11, thực sự có một cách khác: viết một trình lặp tùy chỉnh templatized đơn giản.

giả sử enum của bạn là

enum class foo {
  one,
  two,
  three
};

Mã chung này sẽ thực hiện thủ thuật, khá hiệu quả - đặt trong một tiêu đề chung, nó sẽ phục vụ bạn cho bất kỳ enum nào bạn có thể cần lặp lại:

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

Bạn sẽ cần phải chuyên môn hóa nó

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

Và sau đó bạn có thể lặp lại bằng cách sử dụng phạm vi cho

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

Giả định rằng bạn không có khoảng trống trong enum của bạn vẫn đúng; không có giả định về số lượng bit thực sự cần thiết để lưu trữ giá trị enum (nhờ std :: ngầm_type)


1
@lepe? Bạn chỉ cần tạo một typedef khác cho một enum khác.
Andrew Lazarus

2
@lepe Điều đó giống như nói rằng std::vectorkhông chung chung vì std::vector<foo>được gắn với foo.
Kyle Strand

1
typedef Iterator<color, color::green, color::red> colorIterator;Hãy chắc chắn rằng bạn hiểu cách hoạt động của các mẫu ngay lập tức.
Andrew Lazarus

2
Ồ, tôi thấy vấn đề - foo operator*() { ...nên được C operator*() { ....
Kyle Strand

1
@KyleStrand: Bạn hiểu rồi! Điều đó hoàn toàn có ý nghĩa bây giờ. Mã có nên được cập nhật? Cảm ơn mọi người đã giải thích.
lepe

16

quá nhiều giải pháp phức tạp, tôi làm như thế:

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

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

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

Tôi không biết tại sao điều này đã bị hạ thấp. Đó là một giải pháp hợp lý.
Paul Brannan

11
Tôi hy vọng đó là vì các mục cần phải được duy trì ở hai nơi.
kiến

C ++ có cho phép for (NodePosition pos : NodePositionVector)cú pháp không? Theo như tôi biết đây là cú pháp Java và bạn sẽ cần các trình vòng lặp trong C ++ để làm một cái gì đó tương đương.
thegreatjedi

3
@thegreatjedi Kể từ C ++ 11, bạn có thể, thậm chí là simpier: for (auto pos: NodePocationVector) {..}
Enzojz

@thegreatjedi Sẽ nhanh hơn khi tìm kiếm, hoặc thậm chí biên dịch một chương trình thử nghiệm, hơn là đặt câu hỏi đó. Nhưng vâng, vì C ++ 11, nó là cú pháp C ++ hoàn toàn hợp lệ, trình biên dịch dịch thành mã tương đương (và dài hơn / ít trừu tượng hơn), thường thông qua các trình vòng lặp; xem cppreference . Và, như Enzojz đã nói, C ++ 11 cũng đã thêm auto, vì vậy bạn không phải khai báo loại phần tử một cách rõ ràng, trừ khi bạn (A) cần sử dụng toán tử chuyển đổi hoặc (B) không thích autovì một số lý do . Hầu hết forngười dùng phạm vi sử dụng autoAFAICT
underscore_d

9

Tôi thường làm như thế

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

hoặc nếu không liên tiếp, nhưng với bước thông thường (ví dụ: cờ 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))
    {}

Nhưng, việc sử dụng in các giá trị là gì?
Anu

1
Để sử dụng enums để tạo bitmasks. ví dụ: kết hợp một số tùy chọn trong một biến duy nhất, sau đó sử dụng FOR để kiểm tra cho mọi tùy chọn. Đã sửa bài viết của tôi với ví dụ tốt hơn.
Niki

Tôi vẫn không thể sử dụng nó (& bài viết của bạn vẫn hiển thị ví dụ cũ)! Sử dụng enum như bitmasks thực sự hữu ích, nhưng không thể kết nối các dấu chấm! bạn có thể vui lòng giải thích một chút trong ví dụ của bạn một cách chi tiết, bạn cũng có thể đặt mã bổ sung.
Anu

@anu Xin lỗi không thấy bình luận của bạn. Đã thêm lớp Frog làm ví dụ bitmask
Niki

8

Bạn không thể với một enum. Có lẽ một enum không phù hợp nhất cho tình huống của bạn.

Một quy ước chung là đặt tên giá trị enum cuối cùng giống như MAX và sử dụng giá trị đó để điều khiển vòng lặp bằng int.


Có một số ví dụ ở đây chứng minh điều ngược lại. Tôi tuyên bố của riêng bạn, bạn đang mâu thuẫn với chính mình (dòng thứ hai).
Niki

6

Một cái gì đó chưa được đề cập trong các câu trả lời khác = nếu bạn đang sử dụng các enum C ++ 11 được gõ mạnh, bạn không thể sử dụng ++hoặc sử dụng + intchúng. Trong trường hợp đó, một chút giải pháp lộn xộn là bắt buộc:

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
... nhưng C ++ 11 giới thiệu phạm vi dựa trên đó được hiển thị trong các câu trả lời khác. :-)
hiền triết

5

Bạn có thể thử và xác định macro sau:

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

Bây giờ bạn có thể sử dụng nó:

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

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

Nó có thể được sử dụng để lặp đi lặp lại và chuyển tiếp thông qua không dấu, số nguyên, enums và ký tự:

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


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

Mặc dù định nghĩa vụng về của nó, nó được tối ưu hóa rất tốt. Tôi đã xem xét trình dịch ngược trong VC ++. Mã cực kỳ hiệu quả. Đừng bỏ qua nhưng ba câu lệnh: trình biên dịch sẽ chỉ tạo một vòng lặp sau khi tối ưu hóa! Bạn thậm chí có thể định nghĩa các vòng lặp kèm theo:

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

Bạn rõ ràng không thể lặp qua các kiểu liệt kê với các khoảng trống.


1
Đó là một hack tuyệt vời! Mặc dù nó phù hợp với C hơn là C ++, nhưng người ta có thể nói.
einpoklum

3
_A1không phải là một tên được phép, nó là một dấu gạch dưới hàng đầu với một chữ in hoa sau đây.
Martin Uting

3

Bạn cũng có thể quá tải các toán tử tăng / giảm cho loại liệt kê của bạn.


1
Bạn không thể quá tải bất kỳ toán tử nào trên các kiểu liệt kê C hoặc C ++. Trừ khi bạn tạo ra một cấu trúc / lớp mô phỏng một bảng liệt kê các giá trị.
Trevor Hickey

2
C ++ cho phép quá tải toán tử trên enums. Xem stackoverflow.com/questions/2571456/ trên .
Arch D. Robison

Quá tải mức tăng / giảm yêu cầu đưa ra quyết định phải làm gì khi có tràn
Eponymous

3

Giả sử enum được đánh số liên tục là dễ bị lỗi. Hơn nữa, bạn có thể chỉ muốn lặp lại các điều tra viên được chọn. Nếu tập hợp con đó nhỏ, việc lặp lại nó rõ ràng có thể là một lựa chọn tao nhã:

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

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

Đây là một lựa chọn tốt đẹp tôi nghĩ. Phải là một phần của thông số C ++ mới hơn tôi đang sử dụng khi tôi hỏi câu hỏi tôi đoán?
Adam

Đúng. Nó lặp lại qua một std :: initizer_list <Item>. liên kết .
marski

2

Nếu bạn không muốn làm ô nhiễm enum của bạn với một mục COUNT cuối cùng (bởi vì có thể nếu bạn cũng sử dụng enum trong một công tắc thì trình biên dịch sẽ cảnh báo bạn về trường hợp bị thiếu COUNT :), bạn có thể làm điều này:

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

Đây là một giải pháp khác chỉ hoạt động cho các enum tiếp giáp. Nó mang lại sự lặp lại dự kiến, ngoại trừ sự xấu xí trong gia số, đó là nơi nó thuộc về, vì đó là những gì bị phá vỡ trong 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))
{
    // ...
}

1
Tăng có thể được rút ngắn để foo = Bar(foo + 1).
HolyBlackCat

Cảm ơn, HolyBlackCat, tôi đã kết hợp đề xuất tuyệt vời của bạn! Tôi cũng nhận thấy rằng Riot có khá nhiều giải pháp tương tự, nhưng phù hợp với kiểu gõ mạnh (và do đó dài dòng hơn).
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);
}

Một constexpr std::array có thể lặp lại ngay cả các enum không tuần tự mà không có mảng được trình biên dịch khởi tạo. Điều này phụ thuộc vào những thứ như heuristic tối ưu hóa của trình biên dịch và liệu bạn có lấy địa chỉ của mảng không.

Trong các thử nghiệm của tôi, tôi thấy rằng g++9.1 với -O3sẽ tối ưu hóa mảng trên nếu có 2 giá trị không tuần tự hoặc khá nhiều giá trị tuần tự (tôi đã thử nghiệm lên đến 6). Nhưng nó chỉ làm điều này nếu bạn có một iftuyên bố. . các giá trị từ một enum không tuần tự trong [một trường hợp | https://godbolt.org/z/XuGtoc] . Tôi nghi ngờ hành vi kỳ quặc này là do heuristic sâu phải làm với bộ nhớ cache và dự đoán chi nhánh.

Đây là một liên kết đến một phép lặp thử nghiệm đơn giản trên godbolt để chứng minh rằng mảng không phải lúc nào cũng được khởi tạo.

Giá của kỹ thuật này là viết các phần tử enum hai lần và giữ hai danh sách đồng bộ.


Tôi thích ngữ nghĩa for-loop đơn giản như phạm vi và tôi nghĩ nó sẽ phát triển hơn nữa, đó là lý do tại sao tôi thích giải pháp này.
rtischer8277

2

Trong cuốn sách ngôn ngữ lập trình C ++ của Bjarne Stroustrup, bạn có thể đọc rằng anh ta đang đề xuất quá tải operator++cho cụ thể của bạn enum. enumlà các loại do người dùng định nghĩa và toán tử nạp chồng tồn tại trong ngôn ngữ cho các tình huống cụ thể này.

Bạn sẽ có thể mã như sau:

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

mã kiểm tra: http://cpp.sh/357gb

Tâm trí tôi đang sử dụng enum class. Mã cũng hoạt động tốt với enum. Nhưng tôi thích enum classvì chúng được gõ mạnh và có thể ngăn chúng tôi mắc lỗi vào thời gian biên dịch.


Một downvote đã được đúc trên bài này. Bất kỳ lý do tại sao nó sẽ không trả lời cho câu hỏi?
LAL

Lý do có lẽ là vì đây là một giải pháp khủng khiếp về mặt kiến ​​trúc: nó buộc bạn phải viết logic có nghĩa toàn cầu liên kết với một thành phần cụ thể (liệt kê của bạn), hơn nữa nếu phép liệt kê của bạn thay đổi vì bất kỳ lý do gì bạn buộc phải chỉnh sửa + + nhà điều hành cũng vậy, vì cách tiếp cận không bền vững đối với bất kỳ dự án quy mô vừa nào, không có gì ngạc nhiên khi nó xuất phát từ khuyến nghị của Bjarne Stroustrup, vào thời kỳ kiến ​​trúc phần mềm giống như khoa học viễn tưởng
Manjia

Câu hỏi ban đầu là về việc có một nhà điều hành cho một enum. Đó không phải là một câu hỏi kiến ​​trúc. Tôi không tin rằng năm 2013 C ++ là một khoa học viễn tưởng.
LAL

1

Đối với trình biên dịch 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); 
}

Lưu ý: đây là mã ít hơn nhiều so với câu trả lời lặp tùy chỉnh templatized đơn giản.

Bạn có thể làm cho nó hoạt động với GCC bằng cách sử dụng typeofthay vì decltype, nhưng tôi không có trình biên dịch đó tiện dụng vào lúc này để đảm bảo nó biên dịch.


Điều này đã được viết ~ 5 năm sau khi decltypetrở thành C ++ tiêu chuẩn, vì vậy bạn không nên đề xuất lỗi thời typeoftừ GCC cổ đại. GCC mơ hồ gần đây xử lý decltypetốt. Có một số vấn đề khác: các diễn viên kiểu C không được khuyến khích và các macro tệ hơn. Các tính năng C ++ thích hợp có thể cung cấp cùng chức năng chung. Điều này sẽ được viết lại tốt hơn để sử dụng static_cast& một chức năng mẫu : template <typename T> auto inc_enum(T const t) { return static_cast<T>(static cast<int>(t) + 1); }. Và phôi không cần thiết cho không enum class. Ngoài ra, các nhà khai thác có thể bị quá tải cho mỗi enumloại (TIL)
gạch dưới

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

Giải pháp này sẽ tạo ra một biến tĩnh không cần thiết trong bộ nhớ trong khi mục tiêu của enum chỉ là tạo ra một 'mặt nạ' cho các hằng số được nội tuyến
TheArquitect

Trừ khi đổi thànhconstexpr static const int enumItems[]
Mohammad Kanan

0

C ++ không có nội tâm, vì vậy bạn không thể xác định loại điều này vào thời gian chạy.


1
Bạn có thể giải thích cho tôi tại sao "hướng nội" sẽ cần thiết để lặp lại một enum không?
Jonathan Mee

Có lẽ thuật ngữ là Reflection ?
kͩeͣmͮpͥ

2
Tôi đang cố gắng nói 2 điều: 1) Mỗi ​​câu trả lời khác C ++ có thể thực hiện điều này vì vậy nếu bạn muốn nói điều đó là không thể, thì cần phải có một liên kết hoặc làm rõ thêm. 2) Ở dạng hiện tại, đây là một bình luận, chắc chắn không phải là một câu trả lời.
Jonathan Mee

Từ chối câu trả lời của tôi sau đó - Tôi nghĩ rằng bạn đã chứng minh nhiều hơn
kͩeͣmͮpͥ

1
Tôi sẽ lại nhồi nhét vào 2 bình luận: 1) Tôi không downvote vì tôi thấy rằng việc nhận được sự tham gia của trang web hạ cấp, tôi thấy điều đó phản tác dụng 2) Tôi vẫn không hiểu những gì bạn đang cố nói nhưng nghe có vẻ như bạn hiểu điều gì đó tôi không nên làm trong trường hợp tôi muốn bạn giải thích hơn là xóa câu trả lời bị bỏ qua.
Jonathan Mee

0

Nếu bạn biết rằng các giá trị enum là tuần tự, ví dụ như ent Qt: Key, bạn có thể:

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

Nó hoạt động như mong đợi.


-1

Chỉ cần tạo một mảng ints và lặp qua mảng, nhưng làm cho phần tử cuối cùng nói -1 và sử dụng nó cho điều kiện thoát.

Nếu enum là:

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

sau đó tạo mảng:

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

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

Điều này không bị phá vỡ cho dù các số nguyên trong biểu diễn miễn là kiểm tra -1 không va chạm với một trong các yếu tố của khóa học.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.