-
-
Notifications
You must be signed in to change notification settings - Fork 17
Enhanced enumerations
In Yadoms code, we introduce enhanced enumerations.
The aim of this is to use enumeration either as integer values (common behavior) or as strings.
The use of new enumerations is relatively easy and transparent
Just include an helper file and use included macros.
The helper code should be used as (enhanced) macros. (using boost preprocessor)
There are two steps to use our new enumerations.
- declare header in an header file
- declare implementation in a cpp file
In an header file the following macro declare an enumeration named "EEventType" with 5 values. Each enumeration is associated to an integer (like standard c++ enumeration) starting at 0.
DECLARE_ENUM_HEADER(EEventType,
((Unload))
((Load))
((Crash))
((Info))
((Error))
)
This macros declared the following objects (see 'Switch case' exemple):
Declared | Associated integer |
---|---|
EEventType::kUnload | 0 |
EEventType::kLoad | 1 |
EEventType::kCrash | 2 |
EEventType::kInfo | 3 |
EEventType::kError | 4 |
It is also possible to specify each integer objects (see 'Switch case' exemple):
DECLARE_ENUM_HEADER(EEventType,
((Unload)(-5))
((Load)(8))
((Crash)(0))
((Info)(1))
((Error)(1120))
)
This macros declared the following objects (see 'Switch case' exemple):
Declared | Associated integer |
---|---|
EEventType::kUnload | -5 |
EEventType::kLoad | 8 |
EEventType::kCrash | 0 |
EEventType::kInfo | 1 |
EEventType::kError | 1120 |
In fast the enumeration is declared as a class, which can be shared thourgh libraries. In case you want to export the enumeration with keywords like extern "C" or __declspec(dllexport) there is a dedicated macro which allow adding extra qualifiers to the enumeration.
In this case the YADOMS_SHARED_EXPORT is a platform specific export qualifiers.
DECLARE_ENUM_HEADER_SHARED(EEventType, YADOMS_SHARED_EXPORT,
((Unload))
((Load))
((Crash))
((Info))
((Error))
)
The implementation part is needed to declare strings linked to enumeration values.
The simpler way is to let the macro defining the string associated to the value. The generated string is the enumeration case name , lower case.
DECLARE_ENUM_IMPLEMENTATION(EEventType,
((Unload))
((Load))
((Crash))
((Info))
((Error))
)
Declared | Associated string |
---|---|
EEventType::kUnload | "unload" |
EEventType::kLoad | "load" |
EEventType::kCrash | "crash" |
EEventType::kInfo | "info" |
EEventType::kError | "error" |
In fact, EEventType::kUnload is associated to the string "unload". With any other enumeration EMyEnum::SomeValue_Something, would give "somevalue_something"
It is possible to declare the enumeration strings.
DECLARE_ENUM_IMPLEMENTATION(EEventType,
((Unload)("enum0"))
((Load)("enum1"))
((Crash)("enum2"))
((Info)("enum3"))
((Error)("enum4"))
)
Declared | Associated string |
---|---|
EEventType::kUnload | "enum0" |
EEventType::kLoad | "enum1" |
EEventType::kCrash | "enum2" |
EEventType::kInfo | "enum3" |
EEventType::kError | "enum4" |
In case the enumeration is declared as nested, there is a dedicated macros to declare implementation
DECLARE_ENUM_IMPLEMENTATION_NESTED(CMyClass::EEventType, EEventType,
((Unload))
((Load))
((Crash))
((Info))
((Error))
)
EEventType a; //the first enumeration value is used
EEventType a(0); //use the integer value
EEventType a("load"); //use the string value
EEventType b(a); //use copy constructor
EEventType b(EEventType::kLoad);
EEventType a;
a = 0;
a = "load";
a = EEventType::kLoad;
EEventType b = a;
EEventType a;
a.toString(); // return "unload"
a.toInteger(); // return 0
EEventType::kLoad.toString(); // return "load"
EEventType::kLoad.toInteger(); // return 1
void someMethodWithInt(int value) {...}
void someMethodWithString(std::string value) {...}
EEventType a;
someMethodWithInt(a);
someMethodWithInt(EEventType::kLoad);
someMethodWithString(a);
someMethodWithString(EEventType::kLoad);
This is the only restriction of using the enumeration, declared values cannot be used in case values. For each values, kSomething, there is the constant value kSomethingValue which can be used in case statements.
int someInt;
switch(someInt)
{
case EEventType::kLoad : //do NOT compile
case EEventType::kLoadValue : //compile
}
When Visual Studio will be 100% compliant with C++11, you could update the enumeration macros, so the previous line, which acutally do not compiled, could be used.
According to the C# possibilities, there are methods to check for integer or string definition
if(EEventType::isDefined(4))
{
}
if(EEventType::isDefined("test"))
{
}
Yadoms -- The ultimate house automation solution