1

I sometimes run into situations where i have an enum that has a string constant associated with it and at points in the code I have to replace the enum with the string. e.g.

An enum in my code

typedef enum {
    //define weapon names
    kWeaponGaussRifleType = 1,
    kWeaponGatlingGunType,
    kWeaponSideWinderMissileType,
    kWeaponLaserType
} WeaponType;

Common use for that enum which is perhaps ok.

void fireWeapon(WeaponType w) {
    switch(w) {
        ...
    }
}

Possible incorrect use of that enum which I would like to fix.

void loadAsset(WeaponType w) {
    //associate weapon filename with the weapon type
    if(w == kWeaponGaussRifleType) {
       fileName = "gaussRifle.png"
    } elseif { 
       ...
    }
}

Obviously this code above can be replaced with a switch or it could pick names from an array of strings. But it would still mean that I have to define the entity name twice (once in the enum and then in the code where the translation occurs) and this is thus prone to error and inconsistency in naming.

Is there any way in C++ to fix this?

remudada
  • 3,751
  • 2
  • 33
  • 60
  • You would normally use something like a map for this. What do you mean "prone to error and inconsistency in naming"? – Jon Apr 16 '14 at 08:57
  • Using a map would mean that I lose out on the compile time type checking where I can just pass around the `WeaponType`. – remudada Apr 16 '14 at 08:58
  • possible duplicate of [How to Get enum item name from it's value](http://stackoverflow.com/questions/11714325/how-to-get-enum-item-name-from-its-value) – MoonBun Apr 16 '14 at 08:59
  • 1
    @remudada: Why would you lose out with a `map`? – Jon Apr 16 '14 at 09:00
  • @Jon, with map< WeaponType, string> I would still have to define the enum, and then hardcode the values in the map. Which is still duplication of definition, and error prone. – remudada Apr 16 '14 at 09:22
  • @remudada: Of course you would have to define the enum, but `#include ` isn't that difficult. I still have no idea why you call populating the map "duplication of definition" (it's not definition, it's simply using the proper names of identifiers, not at all different than e.g. referencing `cout`) and "error prone" (the compiler will immediately tell you if you make an error!). – Jon Apr 16 '14 at 09:52
  • Top rated answer here should help. http://stackoverflow.com/a/10966395/2261179 – simurg Apr 16 '14 at 10:24

2 Answers2

5

Yes, you could use X-Macros.

In your header file you define something like this:

#define weapons_list \
X(kWeaponGaussRifleType, 1, "gaussRifle.png") \
X(kWeaponGatlingGunType, 2. "gatlingGun.png") 

Then when you want to define the type:

#define X(a,b,c) a = b;
typedef enum {
    weapons_list
} weaponType;
#undef X

Then your other example:

void loadAsset(WeaponType w) {
    //associate weapon filename with the weapon type
#define X(a,b,c) if (w == a) { fileName = c; }
    weapons_list
#undef X
}
Vicky
  • 12,934
  • 4
  • 46
  • 54
  • +1. To get *slightly* more debuggable preprocessed code, you can put the `X` macros (of course real use requires a much more unique name) into a separate file, one per line, and `#include` that file where you now use the `weapons_list` macro. – Angew is no longer proud of SO Apr 16 '14 at 09:15
  • Looks very interesting, but the useage in loadAssets is rather cryptic . Mortals like me would not be able to understand what's going on. – remudada Apr 16 '14 at 09:25
  • To be clear, the name still have to be defined twice. But at least it is in the same place in the source code to make maintenance safer. – David Heffernan Apr 16 '14 at 10:12
1

But it would still mean that I have to define the entity name twice (once in the enum and then in the code where the translation occurs) and this is thus prone to error and inconsistency in naming. Is there any way in C++ to fix this?

There are no language features in C++ that allow you to recover a textual representation of an enum value. There is no way to avoid the duplication.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. – Pratik Butani Apr 16 '14 at 09:52
  • 1
    @PratikButani I think it answers the question. If you think not then we must understand the question differently. If I were requesting clarification from the asker then I would indeed leave a comment. – David Heffernan Apr 16 '14 at 10:02
  • @PratikButani What makes me think I understand the question correctly is this sentence: *But it would still mean that I have to define the entity name twice (once in the enum and then in the code where the translation occurs) and this is thus prone to error and inconsistency in naming.* – David Heffernan Apr 16 '14 at 10:10