Iterating through range in enum class
DanielH

Enum classes are now preferred over regular enums

How can I iterate using a for loop? I'm not using the entire set only a sub set within the set.

They are integers and my work around is this

#SelectExpand
1// this is a list of integer id for all resources 2 enum class ResourceID 3 { 4 ID_DISPLAY, 5 ID_EVENT_QUEUE, 6 ID_TIMER_LOGIC, 7 ID_BITMAP_BUFFER, 8 ID_BITMAP_FONT, 9 ID_BITMAP_FIRST, 10 ID_BITMAP_MENU_BUTTON_DISABLED = ID_BITMAP_FIRST, 11 ID_BITMAP_MENU_BUTTON_FOCUSED, 12 ID_BITMAP_MENU_BUTTON_NORMAL, 13 ID_BITMAP_MENU_BUTTON_PRESSED, 14 ID_BITMAP_ICON_BUTTON_NORMAL, 15 ID_BITMAP_ICON_BUTTON_PRESSED, 16 ID_BITMAP_BUTTON_ICON_00, 17 ID_BITMAP_BUTTON_ICON_01, 18 ID_BITMAP_BUTTON_ICON_02, 19 ID_BITMAP_BUTTON_ICON_03, 20 ID_BITMAP_BUTTON_ICON_04, 21 ID_BITMAP_ICON_BUTTON_HOVER, 22 ID_BITMAP_CROSSHAIR, 23 ID_BITMAP_ENERGY, 24 ID_BITMAP_SCREEN_GAMEOVER, 25 ID_BITMAP_SCREEN_TITLE, 26 ID_BITMAP_HEART_EMPTY, 27 ID_BITMAP_HEART_FULL, 28 ID_BITMAP_HEART_HALFFULL, 29 ID_BITMAP_ICON_GAME, 30 ID_BITMAP_ICON_ABOUT, 31 ID_BITMAP_ICON_EXIT, 32 ID_BITMAP_ICON_OPTIONS, 33 ID_BITMAP_ICON_START, 34 ID_BITMAP_ITEMS, 35 ID_BITMAP_LOADING, 36 ID_BITMAP_LOGO, 37 ID_BITMAP_MONSTERS, 38 ID_BITMAP_MOUSE, 39 ID_BITMAP_MOUSE_EYE, 40 ID_BITMAP_MOUSE_HAND, 41 ID_BITMAP_MOUSE_WALK, 42 ID_BITMAP_PLAYER, 43 ID_BITMAP_SCROLL, 44 ID_BITMAP_TILES, 45 ID_BITMAP_LAST = ID_BITMAP_TILES 46 }; 47 48// I want to iterate only through the bitmaps 49// I have them coded from bitmap_first to bitmap_last 50// all other functions now take ResourceID as type in place of int 51for (int i = static_cast<int>(ResourceID::ID_BITMAP_FIRST); i <= static_cast<int>(ResourceID::ID_BITMAP_LAST); i++) 52{ 53 ResourceID id = static_cast<ResourceID>(i); 54 Allegro::Bitmap* bitmap = new Allegro::Bitmap(temp, al_destroy_bitmap); 55 if (bitmap) 56 { 57 this->mResourceManager.addResource(id, bitmap); 58 } 59}

Jacob Moena

There are ways to do that -> https://riptutorial.com/cplusplus/example/13085/iteration-over-an-enum

However, since I need to map enums to strings, I simply iterate an unordered_map, like this:

#SelectExpand
1enum class EntityType 2{ 3 none, 4 // static 5 planter, 6 table, 7 table_small, 8... 9}; 10 11using EntityMap = std::unordered_map<std::string, EntityType>; 12 13 EntityMap m_entity_map 14 { 15 {"Unknown", EntityType::none}, 16 // _static 17 {"Planter", EntityType::planter}, 18 {"Table", EntityType::table}, 19 {"Table_Small", EntityType::table_small}, 20... 21};

Then I simply iterate the map. It works great :)

If you don't care about the key, just make it an int, or even an unsigned char.

std::unordered_map is quite fast.

Edit:
I recommend this if you ever needed to switch using std::string ->

#SelectExpand
1bool check_key(EntityMap m, std::string key) 2{ 3 if (m.find(key) == m.end()) 4 return false; 5 6 return true; 7} 8 9EntityType Level::getEntityType(std::string type) 10{ 11 if(!check_key(m_entity_map, type)) 12 { 13 return m_entity_map["Unknown"]; 14 } 15 return m_entity_map[type]; 16}

But I digress :D

torhu

Are you sure you are not turning this on its head, shouldn't the resource objects have a property containing their type? Or maybe even be of different classes?

Jacob Moena

What I do, in my overengineered project, is this ->

#SelectExpand
1enum EntityCategory Level::getEntityCategory(enum EntityType type) 2{ 3 enum EntityCategory cat; 4 switch(type) 5 { 6 case EntityType::none: 7 case EntityType::planter: 8 case EntityType::table: 9 case EntityType::table_small: 10 case EntityType::bowl: 11 case EntityType::urn: 12 case EntityType::body: 13 case EntityType::barrel_wooden: 14 case EntityType::barrel_green: 15 case EntityType::cloth: 16 case EntityType::flag: 17 case EntityType::ceil_gold: 18 case EntityType::ceil_green: 19 case EntityType::stove: 20 case EntityType::bones: 21 case EntityType::skel_remain: 22 case EntityType::well_dry: 23 case EntityType::well_water: 24 case EntityType::lamp: 25 case EntityType::tree: 26 case EntityType::sink: 27 case EntityType::skel_hang: 28 case EntityType::cage: 29 case EntityType::cage_skel: 30 case EntityType::pots_pans: 31 case EntityType::bloody_bones: 32 case EntityType::armor: 33 case EntityType::pillar: 34 case EntityType::blood: 35 case EntityType::bunk: 36 cat = EntityCategory::_static; 37 break; 38 // pickup 39 case EntityType::dogfood: 40 case EntityType::meal: 41 case EntityType::health: 42 case EntityType::ammo: 43 case EntityType::machinegun: 44 case EntityType::chaingun: 45 case EntityType::gold_cross: 46 case EntityType::gold_goblet: 47 case EntityType::gold_casket: 48 case EntityType::gold_crown: 49 cat = EntityCategory::pickup; 50 break; 51 // keys 52 case EntityType::gold_key: 53 case EntityType::silver_key: 54 return EntityCategory::key; 55 break; 56 // enemies 57 case EntityType::guard: 58 case EntityType::dog: 59 case EntityType::officer: 60 case EntityType::ss: 61 cat = EntityCategory::enemy; 62 break; 63 default: 64 cat = EntityCategory::none; 65 }; 66 return cat; 67}

I am not sure if it's the right thing to do, but it works.
Could perhaps be adapted, or serve as a warning? ;D

Thread #618374. Printed from Allegro.cc