मैं एक एनम पर कैसे पुनरावृति कर सकता हूं?


303

मैंने अभी देखा है कि आप एक enum पर मानक गणित संचालकों का उपयोग नहीं कर सकते हैं जैसे कि ++ या + =

तो C ++ enum में सभी मानों के माध्यम से पुनरावृति करने का सबसे अच्छा तरीका क्या है?


2
कई दृष्टिकोणों में से एक: जब एनम जस्ट इज़ नॉट एनफ: एन्युमरेशन क्लासेस फॉर सी ++ । और, यदि आप कुछ अधिक एनकैप्सुलेटेड चाहते हैं, तो जेम्स कांज़ के इस दृष्टिकोण को आज़माएँ।
डॉन वेकफील्ड

लिंक्ड आइटम में कुछ दिलचस्प प्रतिक्रियाएं हैं।
टोनी

ये उत्तर उस समस्या को कवर नहीं करते हैं जो कि intबहुत बड़ी नहीं हो सकती हैं! ( [C++03: 7.2/5])
लाइटनेस दौड़ ऑर्बिट

दिलचस्प है, आप operator++एनम पर परिभाषित कर सकते हैं ; हालाँकि, आप कर सकते हैं for(Enum_E e = (Enum_E)0; e < ENUM_COUNT; e++)। ध्यान दें कि आपको सीम में 0जाना है Enum_Eक्योंकि C ++ एनोम्स पर असाइनमेंट ऑपरेटर को मना करता है।
वेबर 2

यदि कोई संकलित समय ऑपरेटर होता है, तो जिस तरह से आकार के काम करता है, उसी के समान, जो एक std का उत्सर्जन कर सकता है :: initializer_list शाब्दिक में enum के मान शामिल होते हैं, हमारे पास एक समाधान होगा और इसमें कोई रनटाइम ओवरहेड शामिल नहीं होगा।
जब्बूनी

जवाबों:


263

विशिष्ट तरीका इस प्रकार है:

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

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

कृपया ध्यान दें, एनुम Lastका अर्थ है कि इसे पुनरावृत्ति द्वारा छोड़ दिया जाए। इस "नकली" Lastएनम का उपयोग करते हुए , आपको हर बार जब आप एक नई एनम जोड़ना चाहते हैं, तो "अंतिम" एनम में लूप के लिए अपनी समाप्ति स्थिति को अपडेट करने की आवश्यकता नहीं है। यदि आप बाद में अधिक एनम जोड़ना चाहते हैं, तो उन्हें लास्ट से पहले जोड़ें। इस उदाहरण में लूप अभी भी काम करेगा।

यदि एनम मान निर्दिष्ट हैं, तो निश्चित रूप से, यह टूट जाता है:

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

इससे पता चलता है कि एक एनुम वास्तव में के माध्यम से पुनरावृति करने के लिए नहीं है। एक एनुम से निपटने का विशिष्ट तरीका एक स्विच स्टेटमेंट में इसका उपयोग करना है।

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

यदि आप वास्तव में गणना करना चाहते हैं, तो एक वेक्टर में Enum मानों को भर दें और उस पर पुनरावृति करें। यह निर्दिष्ट एनम मूल्यों के साथ ही ठीक से निपटेगा।


13
ध्यान दें कि, उदाहरण के पहले भाग में, यदि आप 'i' को फू एनम के रूप में उपयोग करना चाहते हैं, और इंट का नहीं, तो आपको इसे स्थिर करना होगा जैसे: static_cast <Foo> (i)
क्लेटन

5
इसके अलावा आप लूप में लास्ट कर रहे हैं। होना चाहिए <= अंतिम
टोनी

20
@ टॉनी लास्ट का मतलब है छोड़ दिया जाना। यदि आप बाद में अधिक एनम जोड़ना चाहते हैं, तो उन्हें लास्ट से पहले जोड़ें ... पहले उदाहरण में लूप अभी भी काम करेगा। एक "नकली" अंतिम ईनाम का उपयोग करके, आपको हर बार जब आप एक नई एनम जोड़ना चाहते हैं, तो अंतिम "वास्तविक" एनम में लूप के लिए अपनी समाप्ति स्थिति को अपडेट करने की आवश्यकता नहीं है।
टाइमपीड्यू

सिवाय इसके कि आपने वास्तव में एक एलुम होने पर मेमोरी आवंटित की है, बशर्ते वह शून्य-अनुक्रमित और कड़ाई से निरंतर हो, वह कार्य मेमोरी को आवंटित किए बिना कर सकता है।
बादल

1
ध्यान दें कि अपडेट के लिए सुरक्षित रहने के लिए इस एनम परिभाषा के लिए किसी मान को परिभाषित करना चाहिए UNKNOWN = 0। इसके अलावा, मैं केवल defaultमामले को गिराने का सुझाव दूंगा जब एनम मूल्यों पर स्विच करना होगा क्योंकि यह उन मामलों को छिपा सकता है जहां मूल्यों की हैंडलिंग रनटाइम तक भूल गई थी। इसके बजाय किसी को सभी मूल्यों को हार्डकोड करना चाहिए और UNKNOWNअसंगतताओं का पता लगाने के लिए क्षेत्र का उपयोग करना चाहिए ।
बेंजामिन बैनियर

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

धन्यवाद! ध्यान दें कि यदि आप फ़ाइलों / कक्षाओं को पार कर रहे हैं और यदि एमएस संगतता आपको हेडर-घोषित गैर-पूर्णांक स्थिरांक के साथ समस्या दे रही है, तो यह मेरे कंपाइलर के तहत हेडर के प्रकार में स्पष्ट रूप से आकार डालने में मदद करता है: static const Type All[3];और फिर मैं सक्षम हूं स्रोत में आरंभ करने के लिए: const MyEnum::Type MyEnum::All[3] = { a, b, c }; ऐसा करने से पहले, मुझे अप्रिय Error in range-based for...त्रुटियां हो रही थीं (क्योंकि सरणी में अज्ञात आकार था)। एक संबंधित जवाब के
ऋषि

1
सरणी संस्करण कॉपी पेस्ट के बहुत अनुकूल है। इसके अलावा सबसे संतोषजनक जवाब, "नहीं" या "केवल अनुक्रमिक के लिए"। शायद मैक्रो फ्रेंडली भी।
पाउलो नेव्स

1
यह छोटी संख्या वाली वस्तुओं के लिए enums का एक अच्छा समाधान हो सकता है, लेकिन बड़ी संख्या में आइटम के साथ enums के लिए यह अच्छी तरह से फिट नहीं होना चाहिए।
काटो 2

20

यदि आपकी दुश्मनी 0 से शुरू होती है और वेतन वृद्धि हमेशा 1 होती है।

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

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

यदि नहीं, तो मैं केवल अनुमान लगाता हूं कि कुछ ऐसा क्यों बनाया गया है

vector<enumType> vEnums;

आइटम जोड़ें, और सामान्य पुनरावृत्तियों का उपयोग करें ...।


19

C ++ 11 के साथ, वास्तव में एक विकल्प है: एक साधारण templatized कस्टम पुनरावृत्ति लिखना।

मान लें कि आपकी दुश्मनी है

enum class foo {
  one,
  two,
  three
};

यह जेनेरिक कोड ट्रिक करेगा, काफी कुशलता से - एक जेनेरिक हेडर में जगह, यह आपको किसी भी एनम के लिए आपकी सेवा करेगा जो आपको अधिक पुनरावृति करने की आवश्यकता हो सकती है:

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

आपको इसे विशेषज्ञ बनाने की आवश्यकता होगी

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

और फिर आप रेंज-फॉर का उपयोग करके पुनरावृति कर सकते हैं

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

यह मान लेना कि आपके पास आपकी दुश्मनी में अंतराल नहीं है, अभी भी सच है; वास्तव में Enum मान को संग्रहीत करने के लिए आवश्यक बिट्स की संख्या पर कोई धारणा नहीं है (std के लिए धन्यवाद :: अंतर्निहित_type)


1
@ व्हेल? आप बस एक अलग enum के लिए एक अलग टाइपफ़ेड बनाते हैं।
एंड्रयू लाजर

2
@lepe यह कहना पसंद है कि std::vectorयह सामान्य नहीं है क्योंकि std::vector<foo>यह बंधा हुआ है foo
काइल स्ट्रैंड

1
typedef Iterator<color, color::green, color::red> colorIterator;सुनिश्चित करें कि आप समझते हैं कि टेम्प्लेट इंस्टेंटिएशन कैसे काम करता है।
एंड्रयू लाजर

2
ओह, मैं इस मुद्दे को देखता हूं - foo operator*() { ...होना चाहिए C operator*() { ...
काइल स्ट्रैंड

1
@KyleStrand: आपको मिल गया! यह अब पूरी तरह से समझ में आता है। क्या कोड को अपडेट किया जाना चाहिए? आपके स्पष्टीकरण के लिए सभी को धन्यवाद।
लेप

16

इन समाधानों को बहुत अधिक जटिल, मैं इस तरह से करता हूं:

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

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

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

मुझे नहीं पता कि यह क्यों अस्वीकृत किया गया था। यह एक उचित समाधान है।
पॉल ब्रायनन

11
मुझे उम्मीद है कि यह इसलिए था क्योंकि प्रविष्टियों को दो स्थानों पर बनाए रखा जाना चाहिए।
एंट

क्या C ++ for (NodePosition pos : NodePositionVector)सिंटैक्स की अनुमति देता है ? जहां तक ​​मुझे पता है कि यह जावा सिंटैक्स है, और आपको कुछ समान करने के लिए C ++ में पुनरावृत्तियों की आवश्यकता होगी।
thegreatjedi

3
@thegreatjedi C ++ 11 के बाद से आप कर सकते हैं, यहां तक ​​कि simpier: (ऑटो स्थिति: NodePositionVector) के लिए {..}
Enzojz

@thegreatjedi यह सवाल पूछने की तुलना में खोज या परीक्षण कार्यक्रम को संकलित करने की जल्दी होती। लेकिन हां, C ++ 11 के बाद से यह पूरी तरह से वैध C ++ सिंटैक्स है, जो संकलक समकक्ष (और कहीं अधिक क्रिया / कम अमूर्त) कोड में अनुवाद करता है, आमतौर पर पुनरावृत्तियों के माध्यम से; cppreference देखें । और, जैसा कि एंज़ोज़ ने कहा, सी ++ 11 भी जोड़ा गया है auto, इसलिए आपको तत्वों के प्रकार को स्पष्ट रूप से घोषित करने की आवश्यकता नहीं है, जब तक कि आपको (ए) को रूपांतरण ऑपरेटर का उपयोग करने की आवश्यकता नहीं है या (बी) autoकिसी कारण से पसंद नहीं है । अधिकांश रेंज- forयूजर्स autoAFAICT
underscore_d

9

मैं अक्सर ऐसा ही करता हूं

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

या नहीं तो क्रमिक, लेकिन नियमित रूप से कदम के साथ (उदाहरण के लिए झंडे)

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

लेकिन, बिट-वार को छापने का क्या फायदा है?
अनु

1
बिटमास्क बनाने के लिए एनम का उपयोग करना। उदाहरण के लिए, एकल चर में कई विकल्पों को मिलाएं, फिर प्रत्येक विकल्प के लिए परीक्षण का उपयोग करें। मेरे पोस्ट को बेहतर उदाहरण के साथ तय किया।
निकी

मैं अभी भी इसका उपयोग नहीं कर सकता (और आपकी पोस्ट अभी भी पुराने उदाहरण को दिखाती है)! बिटकॉइन के रूप में एनम का उपयोग करना वास्तव में सहायक है, लेकिन डॉट्स को जोड़ने में सक्षम नहीं है! क्या आप विवरण में अपने उदाहरण में थोड़ा विस्तार कर सकते हैं, आप अतिरिक्त कोड भी डाल सकते हैं।
अनु

@anu क्षमा करें आपकी टिप्पणी नहीं देखी। बिटमेस्क उदाहरण के रूप में मेंढक वर्ग जोड़ा गया
निकी

8

आप एक एनम के साथ नहीं कर सकते। हो सकता है कि आपकी स्थिति के लिए एक फिटतम सबसे उपयुक्त नहीं है।

एक आम सम्मेलन में मैक्स की तरह अंतिम एनम मूल्य का नाम देना और एक इंट का उपयोग करके लूप को नियंत्रित करना है।


यहाँ कई उदाहरण हैं जो विपरीत प्रदर्शित करते हैं। मैं आपका अपना वक्तव्य देता हूं जो आप स्वयं (दूसरी पंक्ति) के विपरीत कर रहे हैं।
निकी

6

ऐसा कुछ जिसे अन्य उत्तरों में शामिल नहीं किया गया है = यदि आप C ++ 11 शब्‍दों का दृढ़ता से उपयोग कर रहे हैं, तो आप उनका उपयोग नहीं कर सकते हैं ++या + intउन पर नहीं कर सकते हैं। उस स्थिति में, एक गन्दा समाधान की आवश्यकता होती है:

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
... लेकिन C ++ 11 उस सीमा का परिचय देता है जिसके लिए अन्य उत्तरों में दिखाया गया है। :-)
ऋषि

5

आप निम्न मैक्रो को आज़मा सकते हैं और परिभाषित कर सकते हैं:

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

अब आप इसका उपयोग कर सकते हैं:

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

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

यह अहस्ताक्षरित, पूर्णांक, एनम और चार्ट के माध्यम से पीछे की ओर और आगे की तरफ करने के लिए इस्तेमाल किया जा सकता है:

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


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

इसकी अजीब परिभाषा के बावजूद इसे बहुत अच्छी तरह से अनुकूलित किया गया है। मैंने वीसी ++ में असंतुष्ट को देखा। कोड अत्यंत कुशल है। बंद मत करो, लेकिन बयानों के लिए तीन: कंपाइलर अनुकूलन के बाद केवल एक लूप का उत्पादन करेगा! तुम भी संलग्न छोरों को परिभाषित कर सकते हैं:

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

आप स्पष्ट रूप से अंतराल के साथ प्रगणित प्रकारों के माध्यम से पुनरावृति नहीं कर सकते।


1
यह एक अद्भुत हैक है! यद्यपि यह C ++ के लिए C से अधिक उपयुक्त है, लेकिन कोई कह सकता है।
ईनपोकलम

3
_A1यह एक स्वीकृत नाम नहीं है, यह निम्नलिखित पूंजी पत्र के साथ एक प्रमुख अंडरस्कोर है।
मार्टिन उडिंग

3

आप अपने एनुमरेटेड प्रकार के लिए इंक्रीमेंट / डिक्रीमेंट ऑपरेटर्स को ओवरलोड भी कर सकते हैं।


1
आप सी या सी ++ एन्यूमरेटेड प्रकार के किसी भी ऑपरेटर को ओवरलोड नहीं कर सकते। जब तक आप एक ऐसा ढांचा / वर्ग तैयार नहीं करते थे जो मूल्यों की गणना करता हो।
ट्रेवर हिक्की

2
सी ++ एनोम्स पर ऑपरेटरों को ओवरलोड करने की अनुमति देता है। Stackoverflow.com/questions/2571456/… देखें ।
आर्क डी। रॉबिसन

ओवरलोडिंग / वेतन वृद्धि को ओवरलोड होने पर निर्णय लेने की आवश्यकता होती है कि अतिप्रवाह क्या है
'18

3

मान लें कि एनम क्रमिक रूप से क्रमांकित है त्रुटि प्रवण है। इसके अलावा, आप केवल चुने हुए प्रगणकों पर पुनरावृति करना चाहते हैं। यदि वह सबसेट छोटा है, तो उस पर लूपिंग स्पष्ट रूप से एक सुंदर विकल्प हो सकता है:

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

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

यह एक अच्छा विकल्प है जो मुझे लगता है। मेरे द्वारा उपयोग किए जा रहे प्रश्न से एक नए C ++ भाग का हिस्सा होना चाहिए जब मैं प्रश्न पूछ रहा हूं?
एडम

हाँ। यह एक std :: initializer_list <आइटम> पर पुनरावृत्त करता है। लिंक
मार्सकी

2

यदि आप एक अंतिम COUNT आइटम के साथ एनम को प्रदूषित करना पसंद नहीं करते हैं (क्योंकि हो सकता है कि अगर आप भी स्विच में एनम का उपयोग करते हैं तो तब कंपाइलर आपको एक लापता मामले COUNT :) के बारे में चेतावनी देगा, आप ऐसा कर सकते हैं:

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

यहाँ एक और उपाय है जो केवल सन्निहित श्लोकों के लिए काम करता है। यह वृद्धि में कुरूपता को छोड़कर अपेक्षित पुनरावृत्ति देता है, जो कि जहां है, वहीं से 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
वृद्धि को छोटा किया जा सकता है foo = Bar(foo + 1)
होलीब्लैककैट 19

धन्यवाद, HolyBlackCat, मैंने आपका उत्कृष्ट सुझाव शामिल किया है! मैं यह भी नोटिस करता हूं कि दंगा में यह एक ही समाधान है, लेकिन मजबूत टाइपिंग (और इस तरह अधिक क्रिया) के अनुरूप है।
एथन ब्रैडफोर्ड

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

एक constexpr std::arrayभी संकलक द्वारा सरणी के बिना सरणी के बिना भी गैर-अनुक्रमिक एनमेंट को पुनरावृत्त कर सकता है। यह कंपाइलर के ऑप्टिमाइज़ेशन हेयुरिस्टिक्स और चाहे आप सरणी का पता ले जैसी चीजों पर निर्भर करता है।

मेरे प्रयोगों में, मैंने पाया कि g++9.1 के साथ -O3उपरोक्त सरणी को दूर कर देगा यदि 2 गैर-अनुक्रमिक मान हैं या कुछ अनुक्रमिक मूल्य हैं (मैंने 6 तक परीक्षण किया)। लेकिन यह केवल अगर आप एक ifबयान है। (मैंने एक कथन की कोशिश की कि सभी तत्वों की तुलना में एक पूर्णांक मान एक अनुक्रमिक सरणी में अधिक है और इसमें किसी को भी बाहर किए जाने के बावजूद पुनरावृत्ति को रेखांकित नहीं किया है, लेकिन जब मैंने कथन छोड़ दिया तो मानों को स्मृति में डाल दिया गया।) एक गैर-अनुक्रमिक एनम से मान [एक मामले में | https://godbolt.org/z/XuGtoc] । मुझे शक है कि यह अजीब व्यवहार गहरी सांख्यिकी के कारण है जो कि कैश और शाखा की भविष्यवाणी के साथ है।

यहाँ गॉडबोल्ट पर एक साधारण परीक्षण पुनरावृत्ति का लिंक दिया गया है जो दर्शाता है कि सरणी हमेशा त्वरित नहीं होती है।

इस तकनीक की कीमत दो बार एनम तत्वों को लिख रही है और दो सूचियों को सिंक में रख रही है।


मुझे लूप शब्दार्थ की तरह सरल रेंज पसंद है और मुझे लगता है कि यह और भी अधिक विकसित होगा, यही वजह है कि मुझे यह समाधान पसंद है।
rtischer8277

2

Bjarne Stroustrup की C ++ प्रोग्रामिंग लैंग्वेज बुक में, आप पढ़ सकते हैं कि वह operator++आपके विशिष्ट के लिए ओवरलोड करने का प्रस्ताव कर रहा है enumenumउपयोगकर्ता-परिभाषित प्रकार हैं और इन विशिष्ट स्थितियों के लिए भाषा में ओवरलोडिंग ऑपरेटर मौजूद है।

आप निम्नलिखित कोड कर सकेंगे:

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

परीक्षण कोड: http://cpp.sh/357gb

मन जो मैं उपयोग कर रहा हूं enum class। कोड enumभी ठीक काम करता है । लेकिन मैं पसंद करता हूं enum classक्योंकि वे मजबूत टाइप के होते हैं और हमें संकलन के समय गलती करने से रोक सकते हैं।


इस पद पर एक उम्मीदवार को उतारा गया। किसी भी कारण से यह प्रश्न का उत्तर नहीं देगा।
LAL

इसका कारण शायद यह है क्योंकि यह एक भयानक समाधान है जो वास्तुशिल्प रूप से बोल रहा है: यह आपको एक विशिष्ट घटक (आपकी गणना) से बंधे हुए वैश्विक-मतलब-तर्क को लिखने के लिए मजबूर करता है, इसके अलावा अगर आपकी गणना आपके कारण संपादित करने के लिए मजबूर हो जाती है + ऑपरेटर भी, एक दृष्टिकोण के रूप में यह किसी भी मध्यम-बड़े पैमाने पर परियोजना के लिए टिकाऊ नहीं है, यह एक आश्चर्य की बात नहीं है कि यह एक
ब्रेज़न स्ट्रॉस्ट्रुप

मूल प्रश्न ऑपरेटर के बारे में है enum। यह एक वास्तुशिल्प प्रश्न नहीं था। मैं नहीं मानता कि 2013 में C ++ एक साइंस फिक्शन था।
LAL 14

1

एमएस कंपाइलर के लिए:

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

ध्यान दें: यह साधारण टेम्पलेटेट किए गए कस्टम पुनरावृत्ति उत्तर की तुलना में बहुत कम कोड है।

आप typeofइसके बजाय जीसीसी के साथ काम करने के लिए इसे प्राप्त कर सकते हैं decltype, लेकिन मेरे पास यह संकलक नहीं है कि यह सुनिश्चित करने के लिए इस समय काम करता है।


यह decltypeमानक C ++ बनने के 5 साल बाद लिखा गया था , इसलिए आपको typeofप्राचीन जीसीसी से पुराने की सिफारिश नहीं करनी चाहिए । हाल ही में जीसीसी decltypeसिर्फ ठीक संभालती है। अन्य मुद्दे हैं: सी-शैली की जातियां हतोत्साहित हैं, और मैक्रोज़ बदतर हैं। उचित C ++ विशेषताएँ समान सामान्य कार्यक्षमता दे सकती हैं। यह बेहतर होगा कि आप static_castएक टेम्पलेट फंक्शन का उपयोग करें और फिर से लिखें template <typename T> auto inc_enum(T const t) { return static_cast<T>(static cast<int>(t) + 1); }:। और गैर के लिए जाति की जरूरत नहीं है enum class। वैकल्पिक रूप से, ऑपरेटरों को प्रति enumप्रकार (टीआईएल) से अधिक भारित किया जा सकता है
अंडरस्कोर_ड

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

यह समाधान एक अनावश्यक रूप से स्थिर चर स्मृति में पैदा करेगा, जबकि
एनम

जब तक नहीं बदलाconstexpr static const int enumItems[]
मोहम्मद कानन

0

C ++ में आत्मनिरीक्षण नहीं है, इसलिए आप रन-टाइम में इस तरह की बात निर्धारित नहीं कर सकते।


1
क्या आप मुझे समझा सकते हैं कि "एन्ट्रोस्पेक्शन" के लिए किसी एनम पर ध्यान केंद्रित करने की आवश्यकता क्यों होगी?
जोनाथन मी

शायद शब्द परावर्तन है ?
k --e'mͮpͥ ͩ

2
मैं 2 बातें कहने की कोशिश कर रहा हूं: 1) कई अन्य उत्तरों के अनुसार C ++ इसे पूरा कर सकता है, यदि आप यह कहने जा रहे हैं कि यह नहीं हो सकता है, तो लिंक या आगे स्पष्टीकरण की आवश्यकता है। 2) यह वर्तमान रूप में यह सबसे अच्छी टिप्पणी है, निश्चित रूप से उत्तर नहीं है।
जोनाथन मी

मेरे उत्तर को तब रद्द करें - मुझे लगता है कि आपने इसे सही ठहराया है
kͣeͮmͥpͥ

1
मैं फिर से 2 टिप्पणियों में रटना चाहूंगा: 1) मैं नीचे नहीं उतरता क्योंकि मुझे लगता है कि एक डाउनवोट डिमोटिव्स साइट की भागीदारी प्राप्त कर रहा है, मुझे लगता है कि मैं प्रतिशोधात्मक 2) मुझे अभी भी समझ में नहीं आ रहा है कि आप क्या कहना चाह रहे हैं लेकिन ऐसा लगता है आप कुछ समझते हैं कि मैं किस स्थिति में नहीं चाहता हूं कि आप एक अस्वीकृत उत्तर को हटाने के बजाय आपको विस्तृत रूप से पसंद करेंगे।
जोनाथन मी

0

यदि आप जानते हैं कि एनम मान अनुक्रमिक थे, उदाहरण के लिए क्यूटी: कुंजी एनम, आप कर सकते थे:

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

यह उम्मीद के मुताबिक काम करता है।


-1

बस सरणी में इन्टस और लूप का एक सरणी बनाएं, लेकिन अंतिम तत्व को -1 कहें और इसे बाहर निकलने की स्थिति के लिए उपयोग करें।

यदि एनम है:

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

फिर सरणी बनाएं:

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

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

यह प्रतिनिधित्व में कोई फर्क नहीं पड़ता जब तक -1 चेक चेक पाठ्यक्रम के तत्वों में से एक के साथ नहीं टकराता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.