9

There are many ways to iterate through consecutive enums like

enum Animal {Cat, Dog, Dolphin}

But is there a convenient and easy way to iterate through non-consecutive enum elements like

enum Animal {Cat = 0, Dog = 5, Dolphin = 8}
stackunderflow
  • 877
  • 4
  • 13
  • 28
  • Not on the `enum` directly. However you can manually put all elements of the `enum` in a container (`vector`, `set`, `unordered_set`, whatever...) and then iterate over that container. – syam Jul 22 '13 at 10:42
  • You mean you want something like `for (Animal a = Cat; a != Dolphin; a++)`? While this works for the first enumeration, it's not something I would personally recommend, as it might be hard to read and understand. – Some programmer dude Jul 22 '13 at 10:43
  • 2
    You can find the answer in this thread http://stackoverflow.com/questions/261963/how-can-i-iterate-over-an-enum . – blitz Jul 22 '13 at 10:46
  • Check also this thread: http://stackoverflow.com/questions/13971544/using-enum-in-loops-and-value-consistency – PaperBirdMaster Jul 22 '13 at 13:33

3 Answers3

3

The short answer to this is "no".

You could make a table animals, and then use a range loop on animals.

Here's a complete "demo":

#include <iostream>

using namespace std;

enum Animal {Cat = 0, Dog = 5, Dolphin = 8};

int main()
{
    Animal animals[] = { Cat, Dog, Dolphin };

    for(Animal a : animals) cout << a << endl;
}

The output will be:

0
5
8
Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
1

You could also provide the necessary operator(s) for the enumeration:

enum Animal
{
  Cat = 0
  , Dog = 5
  , Dolphin = 8
};

inline Animal& operator++ (Animal &x)
{
  switch (x) {
    case Cat:
      x = Dog;
      break;
    case Dog:
      x = Dolphin;
      break;
    case Dolphin:
    default:
      x = static_cast<Animal>(static_cast<int>(x) + 1);
      break;
  }
  return x;
}

DTTO for postfix ++, < and anything else you need. Of course, you have to keep them in sync with the definition of the enumeration. Not really straightforward, but it is an option.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
0

I'm not sure that the question even makes sense. It is at any rate fundamentally impossible. Consider:

enum Animal
{
    cat = 0,
    dog = 5,
    dolphin = 8,
    canine = 5,
    bear = 20
};

When the underlying value is 5, you have no way of determining whether it was set by dog or by canine, and so no way of knowing whether the next value should be dolphin or bear. You could put the values in an array, and iterate over that, but I don't see any other solution.

In general, of course, most of the time you're explicitly affecting values like this this, you're defining a bitmask (e.g. like std::ios_base::fmtflags), and in that case, it makes no sense to iterate. Other use cases I can think of would be special sentinal values (e.g. something like unset), which you would probably want to skip when iterating, or synonyms (like my dog/canine example above), in which case, you'd probably only want to visit one of the synonyms, and realistically, you'd write something like:

enum Animal
{
    cat,
    dog,
    canine = dog,
    dolphin,
    bear
};

, and the usual iteration tricks would result in exactly what you want.

James Kanze
  • 150,581
  • 18
  • 184
  • 329