What happens if I cast an integer into an enum class, but the value is not present in the enum? For example: I want a function that tests if an integer has some value from an enum class:
enum class EnumClass { A, B = 4, C = 9, D = 60 };
bool checkEnumClass( int v )
{
switch( static_cast< EnumClass >( v ) )
{
case EnumClass::A:
case EnumClass::B:
case EnumClass::C:
case EnumClass::D:
return true;
default:
return false;
}
}
checkEnumClass( 0 ) == true;
checkEnumClass( 7 ) == false; // is this true?
Is this the right way to check if an integer is convertible to an enum?
Use the Type Casting to Convert an Int to Enum in C# The correct syntax to use type casting is as follows. Copy YourEnum variableName = (YourEnum)yourInt; The program below shows how we can use the type casting to cast an int to enum in C#. We have cast our integer value to enum constant One .
No, we can have only strings as elements in an enumeration.
Yes. In C enum types are just int s under the covers. Typecast them to whatever you want. enums are not always ints in C.
You can change default values of enum elements during declaration (if necessary).
I don't see any fundamentally better solution than the one offered by the OP. However, it has a small defect for which I can suggest a (non-standard) workaround.
The issue is the following. Suppose the code today is as in the OP but, one day, someone adds a new enumerator to EnumClass
which becomes:
enum class EnumClass { A, B = 4, C = 9, D = 60, E = 70 };
Suppose also that this person forgets to update the definition of checkEnumClass
(which isn't unlikely to happen, especially if the code is in in another file). Then,
checkEnumClass( 70 );
will return false
despite the fact that 70 is now a valid value. Unit tests might help catch this bug but the person must remember to update the test. (Recall that they forgot to update the code at the first place!)
Unfortunately, standard C++ doesn't offer a way to force a switch
on an enum
to cover all the cases (unlike D which offers the final switch
statement).
However, there are compiler-specific features that can do this for you.
For GCC (and, I believe, Clang, as well) you can add the compiler option -Wswitch
(or -Wall
which implies -Wswitch
). For Visual Studio you can add
#pragma warning(error : 4062)
to the file containing checkEnumClass
(not the file containing the enum definition)
Finally, you must slightly change checkEnumClass
because a default
label tells the compiler that all cases are covered. The code should be like this:
bool checkEnumClass( int v )
{
switch( static_cast< EnumClass >( v ) )
{
case EnumClass::A:
case EnumClass::B:
case EnumClass::C:
case EnumClass::D:
return true;
}
return false;
}
With this workaround, the person who included the enumerator E
but forgot to update checkEnumClass
accordingly will get the following error/warning:
GCC:
warning: enumeration value 'E' not handled in switch [-Wswitch]
Visual Studio:
error C4062: enumerator 'E' in switch of enum 'EnumClass' is not handled
switch( static_cast< EnumClass >( v ) )
Update 1: Following the comment by elvis.dukaj.
As a good practice add -Werror
to GCC's options to turn all warnings into errors.
Update 2: Better than -Wswitch
is -Wswitch-enum
which will raise the warning (or error if -Werror
) even when there's a default
label. Unfortunately I don't know any similar feature in Visual Studio.
An enum can hold any value between its smallest and largest values, so what you have is mainly correct. The only thing you need to do additionally is to make sure the integer argument is in the proper range, since if you try to cast an int that is outside the range of the enumeration, you have undefined behavior:
bool checkEnumClass( int v )
{
if (v < static_cast<int>(EnumClass::A)) return false;
if (v > static_cast<int>(EnumClass::D)) return false;
switch( static_cast< EnumClass >( v ) )
{
case EnumClass::A:
case EnumClass::B:
case EnumClass::C:
case EnumClass::D:
return true;
default:
return false;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With