Is it possible to determine if a type is a scoped enumeration type?
I think testing if it is an enum and not implicitly convertible to the underlying type should do the trick.
template <typename T, bool B = std::is_enum<T>::value>
struct is_scoped_enum : std::false_type {};
template <typename T>
struct is_scoped_enum<T, true>
: std::integral_constant<bool,
!std::is_convertible<T, typename std::underlying_type<T>::type>::value> {};
Underlying type of a C++ enum in C++0x
I haven't read any C++0x stuff so I couldn't comment on that.
As for serializing, you don't need the switch when reading the enum back in - just cast it to the enum type.
However, I don't cast when writing to the stream. This is because I often like to write an operator<< for the enum so I can catch bad values being written, or I can then decide to write out a string instead.
enum color { red, green, blue };
color c = red;
// to serialize
archive << c; // Removed cast
// to deserialize
int i;
archive >> i;
c = (color)i; // Removed switch
Is enum class a class type in C++?
enum class
is not a class
definition - the combination of keywords is used to define a scoped enumeration, which is a completely separate entity from a class
.
std::is_class
correctly returns false
here. If you use std::is_enum
, it will return true
.
From the Standard:
The enumeration type declared with an enum-key of only
enum
is an unscoped enumeration, and its enumerators are unscoped enumerators. The enum-keysenum class
andenum struct
are semantically equivalent; an enumeration type declared with one of these is a scoped enumeration, and its enumerators are scoped enumerators.
There is no mention of an enum class
being a "class
type" anywhere in the Standard.
What is the underlying type of a c++ enum?
From N4659 C++ 7.2/5:
For an enumeration whose underlying type is not fixed, the underlying type is an integral type that can represent all the enumerator values defined in the enumeration. If no integral type can represent all the enumerator values, the enumeration is ill-formed. It is implementation-defined which integral type is used as the underlying type except that the underlying type shall not be larger than
int
unless the value of an enumerator cannot fit in anint
orunsigned int
. If the enumerator-list is empty, the underlying type is as if the enumeration had a single enumerator with value 0.
How to safely cast integral types to scoped enums
A common way to do that is to include in your enum an ending marker
enum class Colors : char
{
Red,
Green,
Blue,
Last_Element
}
Using this approach, when converting, you can check if the value you're using is less than the value of Last_Element.
Consider the following function:
template<typename T>
typename std::enable_if<std::is_enum<T>::value, bool>::type
IsValidEnumIntegral<T>(int integral)
{
return (int)(T::Last_Element) > integral;
}
and you could use it like so:
if(IsValidEnumIntegral<Colors>(2))
//do whatever
This would work for any enum you made with an element called Last_Element. You could go further to create a similar function to then auto-convert for you.
Note: This is not tested. I am not in a position to do so at the moment but I think this could work.
EDIT: This will only work if the enum in question uses a set of integers with no gaps for its elements. The function provided will also assume the enum does not contain negative integers, though a First_Element can easily be added to it.
Why does the scoped enum support operator ' ' by default?
If you are referring to the "usual arithmetic conversions", then yes they are done when the arguments are arithmetic or enumeration types. It's just that there is a special bullet there for scoped enums:
[expr]
11 Many binary operators that expect operands of arithmetic or
enumeration type cause conversions and yield result types in a similar
way. The purpose is to yield a common type, which is also the type of
the result. This pattern is called the usual arithmetic conversions,
which are defined as follows:
- If either operand is of scoped enumeration type, no conversions are performed; if the other operand does not have the same type, the expression is ill-formed.
So this case is covered here. Since the two operands are of the same scoped enum type, they are just checked to hold the specific relation in the fashion one would expect.
Can an enum class variable take the full range of integer values?
[dcl.enum]
8 For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type.
Once the underlying type is fixed, any value in its range is a value of the enumeration. The enumerators are just named constants in that range.
There is some minutiae involved in determining when the underlying type is fixed, but it doesn't apply here. A scoped enumeration always has a fixed type (int
if none is given explicitly).
scoped but semi-weakly typed enumerations
For the initialization there is not much you can do other than cast the value. Note that C++11's strongly typed enums are not meant to replace but rather complement the existing enums. If you want a weakly-typed enum, just don't use enum class
.
For the comparison of a strongly-typed enum, you can declare the necessary operators and cast inside the implementation:
bool operator==( uint32_t lhs, SystemEvents rhs )
{
return static_cast< SystemEvent >( lhs ) == rhs;
}
Of course you need both directions:
bool operator==( SystemEvents lhs, uint32_t rhs );
And other operators like !=
.
How to know underlying type of class enum?
Since C++ 11 you can use this:
std::underlying_type
class template to know the underlying type of enum.
The doc says,
Defines a member
typedef
type of type that is the underlying type for the enumeration T.
So you should be able to do this:
#include <type_traits> //include this
FooEnum myEnum;
auto pointer = static_cast<std::underlying_type<FooEnum>::type*>(&myEnum);
In C++ 14 it has been a bit simplified (note there is no ::type
):
auto pointer = static_cast<std::underlying_type_t<FooEnum>*>(&myEnum);
And finally since C++ 23 one can get value without explicit cast (docs):
auto value = std::to_underlying<FooEnum>(myEnum);
Related Topics
Printing Values of All Fields in a C++ Structure
Preventing Compiler Optimizations While Benchmarking
How to Reverse the Order of Arguments of a Variadic Template Function
Rotate Cv::Mat Using Cv::Warpaffine Offsets Destination Image
Specify Template Parameters at Runtime
Using Quaternions for Opengl Rotations
Do All Pointers Have the Same Size in C++
C++11 Static_Assert and Template Instantiation
Getline() Does Not Work If Used After Some Inputs
(Partially) Specializing a Non-Type Template Parameter of Dependent Type
Understanding Return Value Optimization and Returning Temporaries - C++
C++ Threads, Std::System_Error - Operation Not Permitted
Why Does the Most Negative Int Value Cause an Error About Ambiguous Function Overloads
When Including Header Files, Is the Path Case Sensitive