Skip to content

Instantly share code, notes, and snippets.

@dsaltares
Last active December 15, 2022 06:02
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dsaltares/8904478 to your computer and use it in GitHub Desktop.
Save dsaltares/8904478 to your computer and use it in GitHub Desktop.
Smart enums using high order macros in C++
#ifndef __SMARTENUM_H__
#define __SMARTENUM_H__
#include <cstring>
#define SMARTENUM_VALUE(typeName, value) e##typeName##_##value,
#define SMARTENUM_STRING(typeName, value) #value,
#define SMARTENUM_DEFINE_ENUM(typeName, values) enum typeName { values(SMARTENUM_VALUE) e##typeName##_Count, };
#define SMARTENUM_DEFINE_NAMES(typeName, values) const char* typeName##Array [] = { values(SMARTENUM_STRING) };
#define SMARTENUM_DEFINE_GET_VALUE_FROM_STRING(typeName, name) \
typeName get##typeName##FromString(const char* str) \
{ \
for (int i = 0; i < e##typeName##_Count; ++i) \
if (!strcmp(##typeName##Array[i], str)) \
return (##typeName##)i; \
return e##typeName##_Count; \
}
#define getStringFromEnumValue(typeName, value) typeName##Array[##value]
#define getEnumValueFromString(typeName, name) get##typeName##FromString(##name)
#endif // __SMARTENUM_H__
@tomfallen
Copy link

This is quite clever, but it appears that pasting something which is not a valid preprocessor token results in undefined behavior. In particular, I can't get gcc to compile this.

Here's some discussion:
http://stackoverflow.com/questions/1206624/differences-in-macro-concatenation-operator-between-visual-c-and-gcc

@AlexanderAmelkin
Copy link

@dsaltares, sorry, what is this supposed to mean: values(SMARTENUM_VALUE) ?
The values is a macro argument. So, supposedly, you call the macro like this:

SMARTENUM_DEFINE_NAMES(animals, cat dog mouse cow);

Then with g++ -E you, unsurprisingly, get this:

const char* animalsArray [] = { cat dog mouse cow(SMARTENUM_STRING) };;

which of course doesn't compile because it is syntactically incorrect and contains undefined symbols.

@NoureddineHsaini
Copy link

NoureddineHsaini commented Apr 24, 2019

Thank you for sharing this code. Could you help me, I tried to compile this code but I have an error. The error is .

#include
#include
#include

#define SMARTENUM_VALUE(typeName, value) e##typeName##_##value,
#define SMARTENUM_STRING(typeName, value) #value,

#define SMARTENUM_DEFINE_ENUM(typeName, values) enum typeName { values(SMARTENUM_VALUE) e##typeName##_Count };

#define SMARTENUM_DEFINE_NAMES(typeName, values) const char* typeName##Array [] = { values(SMARTENUM_STRING) };

#define SMARTENUM_DEFINE_GET_VALUE_FROM_STRING(typeName, name)
typeName get##typeName##FromString(const char* str)
{
for (int i = 0; i < e##typeName##_Count; ++i) {
if (!strcmp(##typeName##Array[i], str)) {
return (##typeName##)i; }
return e##typeName##_Count; }
}

#define getStringFromEnumValue(typeName, value) typeName##Array[##value]
#define getEnumValueFromString(typeName, name) get##typeName##FromString(##name)

#define ANIMAL_LIST(m)
m(Animal, Dog)
m(Animal, Cat)
m(Animal, Cow)

#define CAR_LIST(m)
m(Car, Fiat)
m(Car, Ford)
m(Car, Audi)
int main()
{

SMARTENUM_DEFINE_ENUM(Animal, ANIMAL_LIST);
SMARTENUM_DEFINE_NAMES(Animal, ANIMAL_LIST);
const char* animalName = getStringFromEnumValue(Animal, eAnimal_Cow);
std::cout << animalName << std::endl;
SMARTENUM_DEFINE_GET_VALUE_FROM_STRING(Animal, animalName);//error here Error (active) ';' waited
Animal animal = getEnumValueFromString(Animal, animalName);
system("pause");
return 0;

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment