What is the best way for non sequencial integer c++ enums - c++

Following the C++ enum pattern I already described here, I was trying to do a similar thing but this time the sequence of values I want to use is not comprehended of continuous integer numbers.
The code is obviously wrong:
class Rotations
{
enum PossibleIndexes
{
ZERO,
PLUS180,
PLUS90,
MINUS90
};
enum PossibleValues
{
ZERO= 0,
PLUS180= 180,
PLUS90= 90,
MINUS90= -90
};
static int Count() { return MINUS90 + 1; }
static PossibleValues Default(){ return ZERO; }
};
as there will be conflicts between elements inherent of the two enums.
So my question is: What is the best approach to implement a fixed number of hardcoded Rotations{0, 180, 90, -90} which has also a Default and a Count functionality?

You can always keep a static std::initializer_list containing all possible values
namespace PossibleValues
{
enum Type
{
ZERO= 0,
PLUS180= 180,
PLUS90= 90,
MINUS90= -90
};
constexpr auto Values = {ZERO, PLUS180, PLUS90, MINUS90};
size_t Count() { return Values.size(); }
Type Default() { return *begin(Values); }
}
This approach will have the added bonus of being able to iterate of the values of the enum in a for-loop
Note: I wish the compiler could generate all that code though, at least for enum class

Disclaimer: I am mentioning an open-source library that I recently published.
You may want to look at Better Enums. It will save you from having to repeat anything.
#include <enum.h>
ENUM(Rotations, int, ZERO = 0, PLUS180 = 180, PLUS90 = 90, MINUS90 = -90)
You could then access the number of constants as
Rotations::_size
There is currently no built-in way of declaring a default value. However, the default constructor is currently private, so you would be forced to provide a value when creating a Rotations value. There is a syntactically "nice" way to do this shown here – look at how invalid is defined using a template. It might be complete overkill for your needs. If you try this library and have any feedback concerning default values, please let me know.
I should note that the count and default value are generated at compile time.

Due to the limitations of Visual C++ 2010 Compilation Toolkit (not fully C++11 compliant), I had to surrender myself to inferior approaches.
The post at https://stackoverflow.com/a/15961043/383779 also suggested me an interesting approach for getting the values.
class Rotations
{
public:
typedef enum
{
ZERO= 0,
PLUS180= 180,
PLUS90 = 90,
MINUS90 = -90
}PossibleValues;
static const PossibleValues PossibleValuesCollection(int index) {
static const PossibleValues values[] = { ZERO, PLUS180, PLUS90, MINUS90 };
return values[index];
}
static int Count() { return 4; }
static PossibleValues Default(){ return ZERO; }
};

Related

Declaring enum as loop boundary [duplicate]

What is the purpose of anonymous enum declarations such as:
enum { color = 1 };
Why not just declare int color = 1?
That's a so-called enum trick for declaring a compile-time integer constant. It's advantage is it guarantees that no variable is instantiated and therefore there's no runtime overhead. Most compilers introduce no overhead with integer constants anyway.
Enums don't take up any space and are immutable.
If you used const int color = 1; then you would solve the mutability issue but if someone took the address of color (const int* p = &color;) then space for it would have to be allocated. This may not be a big deal but unless you explicitly want people to be able to take the address of color you might as well prevent it.
Also when declaring a constant field in a class then it will have to be static const (not true for modern C++) and not all compilers support inline initialization of static const members.
Disclaimer: This answer should not be taken as advice to use enum for all numeric constants. You should do what you (or your co-workers) think is more readable. The answer just lists some reasons one might prefer to use an enum.
If this is old code, then enum might have been used for the "enum hack".
You can learn more about the "enum hack", for example, in this link: enum hack
In short: this allows defining the value once, just like #define or defining a variable, but unlike #define - here the compiler makes sure that the value is a number (int, r-value) and prevents you from doing all kinds of mischief that you can do with the precompiler's simple "search and replace", and unlike defining a variable - never takes up space under any compiler or configuration, and prevents changes to it (even const variables can sometimes be changed if you try hard enough).
(1) int color = 1;
color is changeable (accidently).
(2) enum { color = 1 };
color cannot be changed.
The other option for enum is,
const int color = 1; // 'color' is unmutable
Both enum and const int offer exactly same concept; it's a matter of choice. With regards to popular belief that enums save space, IMO there is no memory constraint related to that, compiler are smart enough to optimize const int when needed.
[Note: If someone tries to use const_cast<> on a const int; it will result in undefined behavior (which is bad). However, the same is not possible for enum. So my personal favorite is enum]
One use of this is when you're doing template metaprogramming, because enum objects are not lvalues, while static const members are. It also used to be a common workaround for compilers that didn't let you initialize static integral constants in the class definition. This is explained in another question.
When you use
enum {color = 1}
you're not using any memory it's like
#define color 1
If you declare a variable
int color=1
Then you're taking up memory for a value that's not to be changed.
Answer
Readability and performance.
Details are describbed as notes to examples below.
Use cases
Personal example
In Unreal Engine 4 (C++ game engine), I have following property (engine exposed member variable):
/// Floor Slope.
UPROPERTY
(
Category = "Movement",
VisibleInstanceOnly,
BlueprintGetter = "BP_GetFloorSlope",
BlueprintReadOnly,
meta =
(
ConsoleVariable = "Movement.FloorSlope",
DisplayName = "Floor Slope",
ExposeOnSpawn = true,
NoAutoLoad
)
)
float FloorSlope = -1.f;
This is a value of floor slope player is standing on (value ∈ [0; 90)°), if any.
Because of engine limitations, it cannot be neither std::optional nor TOptional.
I've came up with a solution to add another self explainable variable bIsOnFloor.
bool bIsOnFloor = false;
My C++ only internal setter for FloorSlope takes the following form:
void UMovement::SetFloorSlope(const float& FloorSlope) noexcept
contract [[expects audit: FloorSlope >= 0._deg && FloorSlope < 90._deg]]
{
this->bIsOnFloor = true;
this->FloorSlope = FloorSlope;
AUI::UI->Debug->FloorSlope = FString::Printf(L"Floor Slope: %2.0f", FloorSlope);
};
Adding special case where FloorSlope parameter would take argument of -1.f would be hard to guess and not user friendly.
Instead, I'd rather create False enum field:
enum { False };
This way, I can simply overload SetFloorSlope function that takes intuitive False instead of -1.f.
void UMovement::SetFloorSlope([[maybe_unused]] const decltype(False)&) noexcept
{
this->bIsOnFloor = false;
this->FloorSlope = -1.f;
AUI::UI->Debug->FloorSlope = L"Floor Slope: —";
};
When a player character hits a floor upon applying gravity to it on tick, I simply call:
SetFloorSlope(FloorSlope);
… where FloorSlope is a float value ∈ [0; 90)°.
Otherwise (if it does not hits a floor), I call:
SetFloorSlope(False);
This form (as opposed to passing -1.f) is much more readable, and self explanatory.
Engine example
Another example may be to prevent or force initialization.
Mentioned above Unreal Engine 4 commonly uses FHitResult struct containing information about one hit of a trace, such as point of impact and surface normal at that point.
This complex struct calls Init method by default, setting some values to certain member variables. This can be forced or prevented (public docs: FHitResult #constructor):
FHitResult()
{
Init();
}
explicit FHitResult(float InTime)
{
Init();
Time = InTime;
}
explicit FHitResult(EForceInit InInit)
{
Init();
}
explicit FHitResult(ENoInit NoInit)
{
}
Epic Games defines such enums similiar, but adds redundant enum names:
enum EForceInit
{
ForceInit,
ForceInitToZero
};
enum ENoInit {NoInit};
Passing NoInit to the constructor of FHitResult prevents initialization, what can lead to performance gain by not initializing values that will be initialized elsewhere.
Community example
FHitResult(NoInit) usage in DamirH's post on Comprehensive GameplayAbilities Analysis Series:
//A struct for temporary holding of actors (and transforms) of actors that we hit
//that don't have an ASC. Used for environment impact GameplayCues.
struct FNonAbilityTarget
{
FGameplayTagContainer CueContainer;
TWeakObjectPtr<AActor> TargetActor;
FHitResult TargetHitResult;
bool bHasHitResult;
public:
FNonAbilityTarget()
: CueContainer(FGameplayTagContainer())
, TargetActor(nullptr)
, TargetHitResult(FHitResult(ENoInit::NoInit))
, bHasHitResult(false)
{
}
// (…)
I dont see it mentioned, another use is to scope your constants. I currently work on code that was written using Visual Studio 2005, and it is now ported to android - g++. In VS2005 you could have code like this enum MyOpts { OPT1 = 1 }; and use it as MyOpts::OPT1 - and compiler did not complain about it, even though it is not valid. g++ reports such code as error, so one solution is to use anonymous enum as follows: struct MyOpts { enum {OPT1 =1}; };, and now both compilers are happy.

Why does this C++ code use an anonymous enum rather than a const variable? [duplicate]

What is the purpose of anonymous enum declarations such as:
enum { color = 1 };
Why not just declare int color = 1?
That's a so-called enum trick for declaring a compile-time integer constant. It's advantage is it guarantees that no variable is instantiated and therefore there's no runtime overhead. Most compilers introduce no overhead with integer constants anyway.
Enums don't take up any space and are immutable.
If you used const int color = 1; then you would solve the mutability issue but if someone took the address of color (const int* p = &color;) then space for it would have to be allocated. This may not be a big deal but unless you explicitly want people to be able to take the address of color you might as well prevent it.
Also when declaring a constant field in a class then it will have to be static const (not true for modern C++) and not all compilers support inline initialization of static const members.
Disclaimer: This answer should not be taken as advice to use enum for all numeric constants. You should do what you (or your co-workers) think is more readable. The answer just lists some reasons one might prefer to use an enum.
If this is old code, then enum might have been used for the "enum hack".
You can learn more about the "enum hack", for example, in this link: enum hack
In short: this allows defining the value once, just like #define or defining a variable, but unlike #define - here the compiler makes sure that the value is a number (int, r-value) and prevents you from doing all kinds of mischief that you can do with the precompiler's simple "search and replace", and unlike defining a variable - never takes up space under any compiler or configuration, and prevents changes to it (even const variables can sometimes be changed if you try hard enough).
(1) int color = 1;
color is changeable (accidently).
(2) enum { color = 1 };
color cannot be changed.
The other option for enum is,
const int color = 1; // 'color' is unmutable
Both enum and const int offer exactly same concept; it's a matter of choice. With regards to popular belief that enums save space, IMO there is no memory constraint related to that, compiler are smart enough to optimize const int when needed.
[Note: If someone tries to use const_cast<> on a const int; it will result in undefined behavior (which is bad). However, the same is not possible for enum. So my personal favorite is enum]
One use of this is when you're doing template metaprogramming, because enum objects are not lvalues, while static const members are. It also used to be a common workaround for compilers that didn't let you initialize static integral constants in the class definition. This is explained in another question.
When you use
enum {color = 1}
you're not using any memory it's like
#define color 1
If you declare a variable
int color=1
Then you're taking up memory for a value that's not to be changed.
Answer
Readability and performance.
Details are describbed as notes to examples below.
Use cases
Personal example
In Unreal Engine 4 (C++ game engine), I have following property (engine exposed member variable):
/// Floor Slope.
UPROPERTY
(
Category = "Movement",
VisibleInstanceOnly,
BlueprintGetter = "BP_GetFloorSlope",
BlueprintReadOnly,
meta =
(
ConsoleVariable = "Movement.FloorSlope",
DisplayName = "Floor Slope",
ExposeOnSpawn = true,
NoAutoLoad
)
)
float FloorSlope = -1.f;
This is a value of floor slope player is standing on (value ∈ [0; 90)°), if any.
Because of engine limitations, it cannot be neither std::optional nor TOptional.
I've came up with a solution to add another self explainable variable bIsOnFloor.
bool bIsOnFloor = false;
My C++ only internal setter for FloorSlope takes the following form:
void UMovement::SetFloorSlope(const float& FloorSlope) noexcept
contract [[expects audit: FloorSlope >= 0._deg && FloorSlope < 90._deg]]
{
this->bIsOnFloor = true;
this->FloorSlope = FloorSlope;
AUI::UI->Debug->FloorSlope = FString::Printf(L"Floor Slope: %2.0f", FloorSlope);
};
Adding special case where FloorSlope parameter would take argument of -1.f would be hard to guess and not user friendly.
Instead, I'd rather create False enum field:
enum { False };
This way, I can simply overload SetFloorSlope function that takes intuitive False instead of -1.f.
void UMovement::SetFloorSlope([[maybe_unused]] const decltype(False)&) noexcept
{
this->bIsOnFloor = false;
this->FloorSlope = -1.f;
AUI::UI->Debug->FloorSlope = L"Floor Slope: —";
};
When a player character hits a floor upon applying gravity to it on tick, I simply call:
SetFloorSlope(FloorSlope);
… where FloorSlope is a float value ∈ [0; 90)°.
Otherwise (if it does not hits a floor), I call:
SetFloorSlope(False);
This form (as opposed to passing -1.f) is much more readable, and self explanatory.
Engine example
Another example may be to prevent or force initialization.
Mentioned above Unreal Engine 4 commonly uses FHitResult struct containing information about one hit of a trace, such as point of impact and surface normal at that point.
This complex struct calls Init method by default, setting some values to certain member variables. This can be forced or prevented (public docs: FHitResult #constructor):
FHitResult()
{
Init();
}
explicit FHitResult(float InTime)
{
Init();
Time = InTime;
}
explicit FHitResult(EForceInit InInit)
{
Init();
}
explicit FHitResult(ENoInit NoInit)
{
}
Epic Games defines such enums similiar, but adds redundant enum names:
enum EForceInit
{
ForceInit,
ForceInitToZero
};
enum ENoInit {NoInit};
Passing NoInit to the constructor of FHitResult prevents initialization, what can lead to performance gain by not initializing values that will be initialized elsewhere.
Community example
FHitResult(NoInit) usage in DamirH's post on Comprehensive GameplayAbilities Analysis Series:
//A struct for temporary holding of actors (and transforms) of actors that we hit
//that don't have an ASC. Used for environment impact GameplayCues.
struct FNonAbilityTarget
{
FGameplayTagContainer CueContainer;
TWeakObjectPtr<AActor> TargetActor;
FHitResult TargetHitResult;
bool bHasHitResult;
public:
FNonAbilityTarget()
: CueContainer(FGameplayTagContainer())
, TargetActor(nullptr)
, TargetHitResult(FHitResult(ENoInit::NoInit))
, bHasHitResult(false)
{
}
// (…)
I dont see it mentioned, another use is to scope your constants. I currently work on code that was written using Visual Studio 2005, and it is now ported to android - g++. In VS2005 you could have code like this enum MyOpts { OPT1 = 1 }; and use it as MyOpts::OPT1 - and compiler did not complain about it, even though it is not valid. g++ reports such code as error, so one solution is to use anonymous enum as follows: struct MyOpts { enum {OPT1 =1}; };, and now both compilers are happy.

Only allow a subset of an enum as return value - OR How to get the compiler to alert me ? in C++

My Goal
I have multiple functions that will return a large List of errorcodes.
Some functions will use same and distinct errorcodes of the "List of errorcodes"
for Example:
fun1() will ONLY return errorcode1 OR errorcode2 (errorcode2 is only used in this function)
fun2() will ONLY return errorcode1 OR errorcode3 (but errorcode1 is used in both functions)
The desired solution should consider the following points:
-
Have a definition what errorcode can be returned by which function
Get compile error if any function tries to return an errorcode that was not intended for this function
Whatever the function return or throws must be convertable to int (because these functions will be part of a C API)
My Approaches
So far I considered to options that use enums but the solutions do not appeal to me
Define for each function a separate enum
Define one global enum for all function
Define for each function a separate enum
enum errorcodefun1 {errorcode1=1, errorcode2=2}; // OK at least it is expressed what is expected for fun1
errorcodefun1 fun1() { };
enum errorcodefun2 {errorcode1_fun2=1, errorcode3_fun2=3 }; // minor problem: not expressing that errorcode1_fun2 is logical same as errorcode1
The more functions (which partly use same errorcode) the more code duplication I get.
Define one enum for all function
enum errorcodes {errorcode1=1, errorcode2=2, errorcode3=3};
errorcode fun1() {... } //do not like because I will get no compilation error if it returns errorcode3. Only errorcode1 and errocode2 is intended
errorcode fun2() {... }
My Question
I was thinking about writing a class that emulates the enum, but so far I see the solution that satisfies all my needs.
Do you have some suggestions or ideas how to accomplish my goal?
How about going with approach #1 but staying safe and expressing the equivalence of the enum members?
enum generic_error {
ERR_OK,
ERR_NOMEM,
ERR_IO,
ERR_GENERIC
};
enum first_error {
FIRSTERR_OK = ERR_OK,
FIRSTERR_NOMEM = ERR_NOMEM
};
enum second_error {
SECONDERR_OK = ERR_OK,
SECONDERR_IO = ERR_IO
};
int main()
{
enum first_error f = FIRSTERR_OK;
enum second_error s = SECONDERR_OK;
assert(f == s); // never fires
return 0;
}
Not that this would be particularly good practice, though... If I were you, I would really just opt to have one common error code enumeration.
Use bitmasks.
enum Code : unsigned int
{
None = 0,
SomeError= 1,
AnotherError = 2,
YetAnotherError = 4
};
unsigned int valid_error_codes_for_func1 = SomeError | YetAnotherError;

The usage of anonymous enums

What is the purpose of anonymous enum declarations such as:
enum { color = 1 };
Why not just declare int color = 1?
That's a so-called enum trick for declaring a compile-time integer constant. It's advantage is it guarantees that no variable is instantiated and therefore there's no runtime overhead. Most compilers introduce no overhead with integer constants anyway.
Enums don't take up any space and are immutable.
If you used const int color = 1; then you would solve the mutability issue but if someone took the address of color (const int* p = &color;) then space for it would have to be allocated. This may not be a big deal but unless you explicitly want people to be able to take the address of color you might as well prevent it.
Also when declaring a constant field in a class then it will have to be static const (not true for modern C++) and not all compilers support inline initialization of static const members.
Disclaimer: This answer should not be taken as advice to use enum for all numeric constants. You should do what you (or your co-workers) think is more readable. The answer just lists some reasons one might prefer to use an enum.
If this is old code, then enum might have been used for the "enum hack".
You can learn more about the "enum hack", for example, in this link: enum hack
In short: this allows defining the value once, just like #define or defining a variable, but unlike #define - here the compiler makes sure that the value is a number (int, r-value) and prevents you from doing all kinds of mischief that you can do with the precompiler's simple "search and replace", and unlike defining a variable - never takes up space under any compiler or configuration, and prevents changes to it (even const variables can sometimes be changed if you try hard enough).
(1) int color = 1;
color is changeable (accidently).
(2) enum { color = 1 };
color cannot be changed.
The other option for enum is,
const int color = 1; // 'color' is unmutable
Both enum and const int offer exactly same concept; it's a matter of choice. With regards to popular belief that enums save space, IMO there is no memory constraint related to that, compiler are smart enough to optimize const int when needed.
[Note: If someone tries to use const_cast<> on a const int; it will result in undefined behavior (which is bad). However, the same is not possible for enum. So my personal favorite is enum]
One use of this is when you're doing template metaprogramming, because enum objects are not lvalues, while static const members are. It also used to be a common workaround for compilers that didn't let you initialize static integral constants in the class definition. This is explained in another question.
When you use
enum {color = 1}
you're not using any memory it's like
#define color 1
If you declare a variable
int color=1
Then you're taking up memory for a value that's not to be changed.
Answer
Readability and performance.
Details are describbed as notes to examples below.
Use cases
Personal example
In Unreal Engine 4 (C++ game engine), I have following property (engine exposed member variable):
/// Floor Slope.
UPROPERTY
(
Category = "Movement",
VisibleInstanceOnly,
BlueprintGetter = "BP_GetFloorSlope",
BlueprintReadOnly,
meta =
(
ConsoleVariable = "Movement.FloorSlope",
DisplayName = "Floor Slope",
ExposeOnSpawn = true,
NoAutoLoad
)
)
float FloorSlope = -1.f;
This is a value of floor slope player is standing on (value ∈ [0; 90)°), if any.
Because of engine limitations, it cannot be neither std::optional nor TOptional.
I've came up with a solution to add another self explainable variable bIsOnFloor.
bool bIsOnFloor = false;
My C++ only internal setter for FloorSlope takes the following form:
void UMovement::SetFloorSlope(const float& FloorSlope) noexcept
contract [[expects audit: FloorSlope >= 0._deg && FloorSlope < 90._deg]]
{
this->bIsOnFloor = true;
this->FloorSlope = FloorSlope;
AUI::UI->Debug->FloorSlope = FString::Printf(L"Floor Slope: %2.0f", FloorSlope);
};
Adding special case where FloorSlope parameter would take argument of -1.f would be hard to guess and not user friendly.
Instead, I'd rather create False enum field:
enum { False };
This way, I can simply overload SetFloorSlope function that takes intuitive False instead of -1.f.
void UMovement::SetFloorSlope([[maybe_unused]] const decltype(False)&) noexcept
{
this->bIsOnFloor = false;
this->FloorSlope = -1.f;
AUI::UI->Debug->FloorSlope = L"Floor Slope: —";
};
When a player character hits a floor upon applying gravity to it on tick, I simply call:
SetFloorSlope(FloorSlope);
… where FloorSlope is a float value ∈ [0; 90)°.
Otherwise (if it does not hits a floor), I call:
SetFloorSlope(False);
This form (as opposed to passing -1.f) is much more readable, and self explanatory.
Engine example
Another example may be to prevent or force initialization.
Mentioned above Unreal Engine 4 commonly uses FHitResult struct containing information about one hit of a trace, such as point of impact and surface normal at that point.
This complex struct calls Init method by default, setting some values to certain member variables. This can be forced or prevented (public docs: FHitResult #constructor):
FHitResult()
{
Init();
}
explicit FHitResult(float InTime)
{
Init();
Time = InTime;
}
explicit FHitResult(EForceInit InInit)
{
Init();
}
explicit FHitResult(ENoInit NoInit)
{
}
Epic Games defines such enums similiar, but adds redundant enum names:
enum EForceInit
{
ForceInit,
ForceInitToZero
};
enum ENoInit {NoInit};
Passing NoInit to the constructor of FHitResult prevents initialization, what can lead to performance gain by not initializing values that will be initialized elsewhere.
Community example
FHitResult(NoInit) usage in DamirH's post on Comprehensive GameplayAbilities Analysis Series:
//A struct for temporary holding of actors (and transforms) of actors that we hit
//that don't have an ASC. Used for environment impact GameplayCues.
struct FNonAbilityTarget
{
FGameplayTagContainer CueContainer;
TWeakObjectPtr<AActor> TargetActor;
FHitResult TargetHitResult;
bool bHasHitResult;
public:
FNonAbilityTarget()
: CueContainer(FGameplayTagContainer())
, TargetActor(nullptr)
, TargetHitResult(FHitResult(ENoInit::NoInit))
, bHasHitResult(false)
{
}
// (…)
I dont see it mentioned, another use is to scope your constants. I currently work on code that was written using Visual Studio 2005, and it is now ported to android - g++. In VS2005 you could have code like this enum MyOpts { OPT1 = 1 }; and use it as MyOpts::OPT1 - and compiler did not complain about it, even though it is not valid. g++ reports such code as error, so one solution is to use anonymous enum as follows: struct MyOpts { enum {OPT1 =1}; };, and now both compilers are happy.

Extending enums in C++?

Is there a way in C++ to extend/"inherit" enums?
I.E:
enum Enum {A,B,C};
enum EnumEx : public Enum {D,E,F};
or at least define a conversion between them?
No, there is not.
enum are really the poor thing in C++, and that's unfortunate of course.
Even the class enum introduced in C++0x does not address this extensibility issue (though they do some things for type safety at least).
The only advantage of enum is that they do not exist: they offer some type safety while not imposing any runtime overhead as they are substituted by the compiler directly.
If you want such a beast, you'll have to work yourself:
create a class MyEnum, that contains an int (basically)
create named constructors for each of the interesting values
you may now extend your class (adding named constructors) at will...
That's a workaround though, I have never found a satistifying way of dealing with an enumeration...
I've solved in this way:
typedef enum
{
#include "NetProtocols.def"
} eNetProtocols, eNP;
Of course, if you add a new net protocol in the NetProtocols.def file, you have to recompile, but at least it's expandable.
"NetProtocols.def" will contain only the field names:
HTTP,
HTTPS,
FTP
I had this problem in some projects that ran on small hardware devices I design. There is a common project that holds a number of services. Some of these services use enums as parameters to get additional type checking and safety. I needed to be able to extend these enums in the projects that use these services.
As other people have mentioned c++ doesn't allow you to extend enums. You can however emulate enums using a namespace and a template that has all the benefits of enum class.
enum class has the following benefits:
Converts to a known integer type.
Is a value type
Is constexpr by default and takes up no valuable RAM on small processors
Is scoped and accessible by enum::value
Works in case statements
Provides type safety when used as a parameter and needs to be explicitly cast
Now if you define a class as an enum you can't create constexpr instances of the enum in the class declaration, because the class is not yet complete and it leads to a compile error. Also even if this worked you could not extend the value set of enums easily later in another file/sub project .
Now namespaces have no such problem but they don't provide type safety.
The answer is to first create a templated base class which allows enums of different base sizes so we don't waste what we don't use.
template <typename TYPE>
class EnumClass {
private:
TYPE value_;
public:
explicit constexpr EnumClass(TYPE value) :
value_(value){
}
constexpr EnumClass() = default;
~EnumClass() = default;
constexpr explicit EnumClass(const EnumClass &) = default;
constexpr EnumClass &operator=(const EnumClass &) = default;
constexpr operator TYPE() const {return value_;}
constexpr TYPE value() const {return value_;}
};
Then for each enum class we want to extend and emulate we create a namespace and a Type like this:
namespace EnumName {
class Type :public Enum<uint8_t> {
public:
explicit constexpr Type(uint8_t value): Enum<uint8_t>(value){}
constexpr Enum() = default;
}
constexpr auto Value1 = Type(1);
constexpr auto Value2 = Type(2);
constexpr auto Value3 = Type(3);
}
Then later in your code if you have included the original EnumName you can do this:
namespace EnumName {
constexpr auto Value4 = Type(4U);
constexpr auto Value5 = Type(5U);
constexpr auto Value6 = Type(6U);
constexpr std::array<Type, 6U> Set = {Value1, Value2, Value3, Value4, Value5, Value6};
}
now you can use the Enum like this:
#include <iostream>
void fn(EnumName::Type val){
if( val != EnumName::Value1 ){
std::cout << val;
}
}
int main(){
for( auto e :EnumName::Set){
switch(e){
case EnumName::Value1:
std::cout << "a";
break;
case EnumName::Value4:
std::cout << "b";
break;
default:
fn(e);
}
}
}
So we have a case statement, enum comparisons, parameter type safety and its all extensible. Note the set is constexpr and wont end up using valuable RAM on a small micro (placement verified on Godbolt.org. :-). As a bonus we have the ability to iterate over a set of enum values.
If you were able to create a subclass of an enum it'd have to work the other way around.
The set of instances in a sub-class is a subset of the instances in the super-class. Think about the standard "Shape" example. The Shape class represents the set of all Shapes. The Circle class, its subclass, represents the subset of Shapes that are Circles.
So to be consistent, a subclass of an enum would have to contain a subset of the elements in the enum it inherits from.
(And no, C++ doesn't support this.)
A simple, but useful workaround for this c++ gap could be as follows:
#define ENUM_BASE_VALS A,B,C
enum Enum {ENUM_BASE_VALS};
enum EnumEx {ENUM_BASE_VALS, D,E,F};
Actually you can extend enums in a round about way.
The C++ standard defines the valid enum values to be all the valid values of the underlying type so the following is valid C++ (11+). Its not Undefined Behaviour, but it is very nasty - you have been warned.
#include <cstdint>
enum Test1:unit8_t {
Value1 =0,
Value2 =1
};
constexpr auto Value3 = static_cast<Test1>(3);
constexpr auto Value4 = static_cast<Test1>(4);
constexpr auto Value5 = static_cast<Test1>(5);
Test1 fn(Test1 val){
switch(val){
case Value1:
case Value2:
case Value3:
case Value4:
return Value1;
case Value5:
return Value5;
}
}
int main(){
return static_cast<uint8_t>(fn(Value5));
}
Note that most of the compilers don't consider the additional values as part of the set for generating warnings about missing enums values in switch statements.So
clang and gcc will warn if Value2 is missing but will do nothing if Value4 is missing in the above switch statement.
One might try this :)
struct EnumType
{
enum
{
None = 0,
Value_1 = 1,
Value_2 = 2,
Value_3 = 3
};
//For when using the EnumType as a variable type
int Value { None };
};
struct EnumTypeEx : EnumType
{
enum
{
ExValue_1 = 3,
ExValue_2 = 4,
//override the value of Value_3
Value_3 = 3000
};
};
Pros:
Class like extensibility
Can override base labels value
Cons:
Tedious to write
You have to explicitly set the value for each label(*)
(*) you can start the auto value increment from the last base value by just writing it explicitly eg. ExValue_Start = LastBaseValue.
I do this
enum OPC_t // frame Operation Codes
{
OPC_CVSND = 0 // Send CV value
, OPC_CVREQ = 1 // Request CV (only valid for master app)
, OPC_COMND = 2 // Command
, OPC_HRTBT = 3 // Heart Beat
};
enum rxStatus_t // this extends OPC_t
{
RX_CVSND = OPC_CVSND // Send CV value
, RX_CVREQ = OPC_CVREQ // Request CV
, RX_COMND = OPC_COMND // Command
, RX_HRTBT = OPC_HRTBT // Heart Beat
, RX_NONE // No new Rx
, RX_NEWCHIP // new chip detected
};
http://www.codeproject.com/KB/cpp/InheritEnum.aspx goes over a method to created an expanded enum.
Create InheritEnum.h:
// -- InheritEnum.h
template <typename EnumT, typename BaseEnumT>
class InheritEnum
{
public:
InheritEnum() {}
InheritEnum(EnumT e)
: enum_(e)
{}
InheritEnum(BaseEnumT e)
: baseEnum_(e)
{}
explicit InheritEnum( int val )
: enum_(static_cast<EnumT>(val))
{}
operator EnumT() const { return enum_; }
private:
// Note - the value is declared as a union mainly for as a debugging aid. If
// the union is undesired and you have other methods of debugging, change it
// to either of EnumT and do a cast for the constructor that accepts BaseEnumT.
union
{
EnumT enum_;
BaseEnumT baseEnum_;
};
};
And then to use:
enum Fruit { Orange, Mango, Banana };
enum NewFruits { Apple, Pear };
typedef InheritEnum< NewFruit, Fruit > MyFruit;
void consume(MyFruit myfruit);
YMMV.
Just an idea:
You could try to create an empty class for each constant (maybe put them all in the same file to reduce clutter), create one instance of each class and use the pointers to these instances as the "constants". That way, the compiler will understand inheritance and will perform any ChildPointer-to-ParentPointer conversion necessary when using function calls, AND you still get type-safety checks by the compiler to ensure no one passes an invalid int value to functions (which would have to be used if you use the LAST value method to "extend" the enum).
Haven't fully thought this through though so any comments on this approach are welcome.
And I'll try to post an example of what I mean as soon as I have some time.
My approach slightly differs from that chosen by Marco.
I have added a macro as the last value of the enum I want to extend. In a separate header, I have defined that macro with the enum entries I want to add.
// error.h
#ifndef __APP_DEFINED__
#define __APP_DEFINED__
#endif
typedef enum { a, b, c, __APP_DEFINED__ } Error;
To add more values, I have created
// app_error.h
#define __APP_DEFINED__ d, e, f,
Lastly, I have added -include app_error.h to the compiler flags.
I prefer this approach compared to placing an #include "app_error.h" directive within the enum, mainly because I need the freedom not to have the "app_error.h" file at all in some projects.
The following code works well.
enum Enum {A,B,C};
enum EnumEx {D=C+1,E,F};