How can I iterate over an enum?
The typical way is as follows:
enum Foo {
One,
Two,
Three,
Last
};
for ( int fooInt = One; fooInt != Last; fooInt++ )
{
Foo foo = static_cast<Foo>(fooInt);
// ...
}
Please note, the enum Last
is meant to be skipped by the iteration. Utilizing this "fake" Last
enum, you don't have to update your terminating condition in the for loop to the last "real" enum each time you want to add a new enum.
If you want to add more enums later, just add them before Last. The loop in this example will still work.
Of course, this breaks down if the enum values are specified:
enum Foo {
One = 1,
Two = 9,
Three = 4,
Last
};
This illustrates that an enum is not really meant to iterate through. The typical way to deal with an enum is to use it in a switch statement.
switch ( foo )
{
case One:
// ..
break;
case Two: // intentional fall-through
case Three:
// ..
break;
case Four:
// ..
break;
default:
assert( ! "Invalid Foo enum value" );
break;
}
If you really want to enumerate, stuff the enum values in a vector and iterate over that. This will properly deal with the specified enum values as well.
Iterate through enums in C?
I'd probably define a struct
struct RegInfo
{
registers number;
values defaultValue;
}
Then I would create an array matching the register number to the default value
struct RegInfo registerInfo[] =
{
{ REG1, VALUE_REG1 },
{ REG2, VALUE_REG2 },
{ REG3, VALUE_REG3 },
{ REG4, VALUE_REG4 },
{ REG5, VALUE_REG5 },
{ REG6, VALUE_REG6 },
};
Now to iterate the registers:
for (int i = 0 ; i < sizeof registerInfo / sizeof(RegInfo) ; ++i)
{
values value = readFromReg( registerInfo[i].number);
if (value != registerInfo[i].defaultValue)
{
// Not the default
}
}
If you want an inner loop foe each value, same trick except the array can be directly of the values
values allValues[] = { VALUE_REG1, Value_REG2, ... , VALUE_REG6 };
There is a risk that you'll forget to put new values/registers in the relevant array, but that's what unit testing is for.
How to enumerate an enum
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}
Note: The cast to (Suit[])
is not strictly necessary, but it does make the code 0.5 ns faster.
What are commonly-used ways to iterate over an enum class in C++?
This is the most-readable and simplest approach I could come up with, but I am open to other peoples' example solutions.
I find this approach to be easy-to-use, similar to my C approach (making it more-portable and more-recognizable), and suitable to C++. It compiles with the -Wall -Wextra -Werror
compiler build options.
enum class MyErrorType
{
SOMETHING_1 = 0,
SOMETHING_2,
SOMETHING_3,
SOMETHING_4,
SOMETHING_5,
/// Not a valid value; this is the number of members in this enum
_COUNT,
// helpers for iterating over the enum
begin = 0,
end = _COUNT,
};
for (MyErrorType myErrorType = (MyErrorType)0;
myErrorType < MyErrorType::_COUNT;
myErrorType = static_cast<MyErrorType>((size_t)myErrorType + 1))
{
switch (myErrorType)
{
case MyErrorType::SOMETHING_1:
break;
case MyErrorType::SOMETHING_2:
break;
case MyErrorType::SOMETHING_3:
break;
case MyErrorType::SOMETHING_4:
break;
case MyErrorType::SOMETHING_5:
break;
case MyErrorType::_COUNT:
// This case will never be reached. It is included only so that when
// compiling with `-Wall -Wextra -Werror` build flags you get the
// added bonus of covering all switch cases (withOUT unnecessarily
// relying on a `default` case which would break this feature!), so
// if you ever add a new element to the enum class but forget to
// add it here to the switch case the compiler will THROW AN ERROR.
// This is an added safety benefit to force you to keep your enum
// and the switch statement in-sync! It's a technique commonly used
// in C as well.
break;
}
}
Read my comments for the MyErrorType::_COUNT
case above! If you are using the compiler's -Wall -Wextra -Werror
compiler options but do NOT include this case in the switch statement (since those build options require you to cover ALL enum cases in ALL switch statements!), the compiler will throw the following error and stop! This is a great safety feature to ensure you keep the enum definition and all switch cases in-sync, handling all possible enums in all of your switch statements. Here is the compiler error thrown by LLVM's clang compiler (an alternative to gcc):
../my_file.cpp:11:16: error: enumeration value ‘_COUNT’ not handled in switch [-Werror=switch]
11 | switch (myErrorType) {
| ^
One more tiny improvement over the code above, for clarity, would be to add begin
and end
elements to your enum like this:
enum class MyErrorType
{
SOMETHING_1 = 0,
SOMETHING_2,
SOMETHING_3,
SOMETHING_4,
SOMETHING_5,
/// Not a valid value; this is the number of members in this enum
_COUNT,
// helpers for iterating over the enum
begin = 0,
end = _COUNT,
};
...so that you can iterate over the enum as follows. The incrementing part of the for
loop still is a bit cumbersome with all of the required casts, but the initial state and end condition check are at least much clearer now, since they use MyErrorType::begin
and MyErrorType::end
:
for (MyErrorType myErrorType = MyErrorType::begin;
myErrorType < MyErrorType::end;
myErrorType = static_cast<MyErrorType>((size_t)myErrorType + 1))
{
switch (myErrorType)
{
case MyErrorType::SOMETHING_1:
break;
case MyErrorType::SOMETHING_2:
break;
case MyErrorType::SOMETHING_3:
break;
case MyErrorType::SOMETHING_4:
break;
case MyErrorType::SOMETHING_5:
break;
case MyErrorType::_COUNT:
// This case will never be reached.
break;
}
}
Related:
- Common techniques for iterating over
enum
s (as opposed toenum class
es): How can I iterate over an enum?- [my answer] How can I iterate over an enum?
- My answer on some of the differences between
enum class
es (strongly-typed enums) and regularenum
s (weakly-typed enums) in C++: How to automatically convert strongly typed enum into int? - Some of my personal notes on the
-Wall -Wextra -Werror
and other build options, from my eRCaGuy_hello_world repo. - Incrementation and decrementation of “enum class”
Other keywords: common way to iterate over enum or enum class in C or C++; best way to iterate over enum class in C++; enum class C++ iterate; c++ iterate over enum class
How to Iterate only directly set enum values in plain c?
Though the attractiveness of the following alternative isn't heartwarming, it is none-the-less likely effective for the platform you're currently using.
The language doesn't support enumeration of enum
values as a built-in construct. There are ways to "fake" it though. Once such way is by providing your own table-of-enum, then enumerating that. I will argue, however, whether this is "better". Easier to type, yes. Logical, maybe. but your switch statement is most-assuredly going to compile down to more efficient code. I would be shocked if it didn't.
typedef enum {
// Determine position of Red and Green color:
// RED[2:0], GREEN[5:3], BLUE implicitly. Thus, [7:6]==!0
LED_BO_RedGreenBlue=0b00010001,
LED_BO_RedBlueGreen=0b00100001,
LED_BO_GreenBlueRed=0b00001100,
LED_BO_GreenRedBlue=0b00001010,
LED_BO_BlueRedGreen=0b00100010,
LED_BO_BlueGreenRed=0b00010100,
} led_byteorder_values_t;
static const led_byteorder_values_t led_byteorder_values[] =
{
LED_BO_RedGreenBlue,
LED_BO_RedBlueGreen,
LED_BO_GreenBlueRed,
LED_BO_GreenRedBlue,
LED_BO_BlueRedGreen,
LED_BO_BlueGreenRed
};
static const size_t size_led_byteorder_values =
sizeof(led_byteorder_values)/sizeof(*led_byteorder_values);
With that you can enumerate the values directly via a [0...size_led_byteorder_values)
loop. you can still custom-order the loop by adjusting the table entry order for most-to-least-likely hit for quicker loop-exit. But again, it isn't like that isn't possible with a decently formed switch such as yours.
Anyway, its a thought, and I feel your pain. Its one of the few features that not-just-C++, but most languages don't offer, and it certainly seems to pop up as useful once in awhile.
Best of luck.
Can you loop through an enum in C#?
You should be able to utilize the following:
foreach (MY_ENUM enumValue in Enum.GetValues(typeof(MY_ENUM)))
{
// Do work.
}
Enumerate over an enum in C++
To add to @StackedCrooked answer, you can overload operator++
, operator--
and operator*
and have iterator like functionality.
enum Color {
Color_Begin,
Color_Red = Color_Begin,
Color_Orange,
Color_Yellow,
Color_Green,
Color_Blue,
Color_Indigo,
Color_Violet,
Color_End
};
namespace std {
template<>
struct iterator_traits<Color> {
typedef Color value_type;
typedef int difference_type;
typedef Color *pointer;
typedef Color &reference;
typedef std::bidirectional_iterator_tag
iterator_category;
};
}
Color &operator++(Color &c) {
assert(c != Color_End);
c = static_cast<Color>(c + 1);
return c;
}
Color operator++(Color &c, int) {
assert(c != Color_End);
++c;
return static_cast<Color>(c - 1);
}
Color &operator--(Color &c) {
assert(c != Color_Begin);
return c = static_cast<Color>(c - 1);
}
Color operator--(Color &c, int) {
assert(c != Color_Begin);
--c;
return static_cast<Color>(c + 1);
}
Color operator*(Color c) {
assert(c != Color_End);
return c;
}
Let's test with some <algorithm>
template
void print(Color c) {
std::cout << c << std::endl;
}
int main() {
std::for_each(Color_Begin, Color_End, &print);
}
Now, Color
is a constant bidirectional iterator. Here is a reusable class i coded while doing it manually above. I noticed it could work for many more enums, so repeating the same code all over again is quite tedious
// Code for testing enum_iterator
// --------------------------------
namespace color_test {
enum Color {
Color_Begin,
Color_Red = Color_Begin,
Color_Orange,
Color_Yellow,
Color_Green,
Color_Blue,
Color_Indigo,
Color_Violet,
Color_End
};
Color begin(enum_identity<Color>) {
return Color_Begin;
}
Color end(enum_identity<Color>) {
return Color_End;
}
}
void print(color_test::Color c) {
std::cout << c << std::endl;
}
int main() {
enum_iterator<color_test::Color> b = color_test::Color_Begin, e;
while(b != e)
print(*b++);
}
Implementation follows.
template<typename T>
struct enum_identity {
typedef T type;
};
namespace details {
void begin();
void end();
}
template<typename Enum>
struct enum_iterator
: std::iterator<std::bidirectional_iterator_tag,
Enum> {
enum_iterator():c(end()) { }
enum_iterator(Enum c):c(c) {
assert(c >= begin() && c <= end());
}
enum_iterator &operator=(Enum c) {
assert(c >= begin() && c <= end());
this->c = c;
return *this;
}
static Enum begin() {
using details::begin; // re-enable ADL
return begin(enum_identity<Enum>());
}
static Enum end() {
using details::end; // re-enable ADL
return end(enum_identity<Enum>());
}
enum_iterator &operator++() {
assert(c != end() && "incrementing past end?");
c = static_cast<Enum>(c + 1);
return *this;
}
enum_iterator operator++(int) {
assert(c != end() && "incrementing past end?");
enum_iterator cpy(*this);
++*this;
return cpy;
}
enum_iterator &operator--() {
assert(c != begin() && "decrementing beyond begin?");
c = static_cast<Enum>(c - 1);
return *this;
}
enum_iterator operator--(int) {
assert(c != begin() && "decrementing beyond begin?");
enum_iterator cpy(*this);
--*this;
return cpy;
}
Enum operator*() {
assert(c != end() && "cannot dereference end iterator");
return c;
}
Enum get_enum() const {
return c;
}
private:
Enum c;
};
template<typename Enum>
bool operator==(enum_iterator<Enum> e1, enum_iterator<Enum> e2) {
return e1.get_enum() == e2.get_enum();
}
template<typename Enum>
bool operator!=(enum_iterator<Enum> e1, enum_iterator<Enum> e2) {
return !(e1 == e2);
}
Iterating over non-incremental Enum
With C++, the only way to iterate through enums is store them in an array and iterate through the same. The main challenge is how to track the same order in the enum
declaration and the array declaration?
You can automate the way you order them in the enum
as well as array. I feel that this is a decent way:
// CAPI_SUBTYPE_E_list.h
// This header file contains all the enum in the order
// Whatever order is set will be followed everywhere
NAME_VALUE(CAPI_SUBTYPE_NULL, 0), /* Null subtype. */
NAME_VALUE(CAPI_SUBTYPE_DIAG_DFD, 1), /* Data Flow diag. */
NAME_VALUE(CAPI_SUBTYPE_DIAG_ERD, 2), /* Entity-Relationship diag. */
...
NAME_VALUE(CAPI_SUBTYPE_DD_ALL, 13), /* DD Entries (All). */
NAME_VALUE(CAPI_SUBTYPE_DD_COUPLE, 14), /* DD Entries (Couples). */
...
NAME_VALUE(CAPI_SUBTYPE_DIAG_ASG, 59) /* ASG diagram. */
Now you #include
this file in your enum declaration and array declaration both places with macro redefinition:
// Enum.h
typedef enum {
#define NAME_VALUE(NAME,VALUE) NAME = VALUE
#include"CAPI_SUBTYPE_E_list.h"
#undef NAME_VALUE
}CAPI_SUBTYPE_E;
And put the same file for array with other macro definition:
// array file
// Either this array can be declared `static` or inside unnamed `namespace` to make
// ... it visible through a header file; Or it should be declared `extern` and keep ...
// ... the record of its size; declare a getter method for both array and the size
unsigned int CAPI_SUBTYPE_E_Array [] = {
#define NAME_VALUE(NAME,VALUE) NAME
#include"CAPI_SUBTYPE_E_list.h"
#undef NAME_VALUE
};
Now iterate in C++03 as:
for(unsigned int i = 0, size = sizeof(CAPI_SUBTYPE_E_Array)/sizeof(CAPI_SUBTYPE_E_Array[0]);
i < size; ++i)
or yet simple in C++11:
for(auto i : CAPI_SUBTYPE_E_Array)
Related Topics
C++ Compare Char Array with String
How to Set a Breakpoint in Gdb Where the Function Returns
What Is the Point of a Private Pure Virtual Function
C++ Function to Count All the Words in a String
Which Headers in the C++ Standard Library Are Guaranteed to Include Another Header
How to 'Cout' the Correct Number of Decimal Places of a Double Value
Passing Arguments to Std::Async by Reference Fails
Serial Comm Using Writefile/Readfile
C++11 Inheriting Constructors and Access Modifiers
Are Memory Leaks "Undefined Behavior" Class Problem in C++
Why Are Memcpy() and Memmove() Faster Than Pointer Increments
Using Cmake with Multiple Compilers for the Same Language
Opencv Error: Assertion Failed (Size.Width>0 && Size.Height>0) Simple Code
How to Iterate Over a Packed Variadic Template Argument List