I have an event handler class that uses a template argument to set the event type. I want to enforce these event types to be enum classes of one byte size. Static assertion against the size is not an issue, but I cannot find information online on how to statically distinguish between an enum and enum class.
The solution I have now is to assert for enums using the C++ front-end implements syntactic extensions and then assert the correct size. On most platforms this works, since an enum uses the int
type (which most often is larger than one byte).
But this would lead to slightly misleading error messages. I like to be thorough.
What checks could I do that would pass on a class enum, but fail with a regular old enum?
I cannot use type_traits
, since the compiler I use (avr-gcc) does not support it. I am however continuously implementing my own type_traits
, when a need rises. So any tips on solutions in type_traits
could still be useful!
Minimal example:
// Event types
enum class tPass : uint8_t {};
enum class tFailSize : uint16_t {}; // Fail on size!
enum tFailType {}; // Currently fails on size, would like to fail on type!
// Event handler
template <typename TEvent>
class tEventHandler
{
static_assert(__is_enum(TEvent), "Must be class enum!"); // Doesn't really check for CLASS enums
static_assert(1 == sizeof(TEvent), "Must be one byte!");
};
Usage:
auto handler = tEventHandler<tPass>(); // Ok!
// auto handler2 = tEventHandler<tFailSize>(); // error: static assertion failed: Must be one byte!
// auto handler3 = tEventHandler<tFailType>(); // error: static assertion failed: Must be one byte! <----- THIS
Goal:
auto handler = tEventHandler<tPass>(); // Ok!
// auto handler2 = tEventHandler<tFailSize>(); // error: static assertion failed: Must be one byte!
// auto handler3 = tEventHandler<tFailType>(); // error: static assertion failed: Must be class enum! <--- THIS
Difference between Enums and Classes An enum can, just like a class , have attributes and methods. The only difference is that enum constants are public , static and final (unchangeable - cannot be overridden).
enum can not be static. enum is a type and can be defined independently or inside a class (which is also a type). Since many years I use a "static" type of enumerations.
Enumeration or Enum in C is a special kind of data type defined by the user. It consists of constant integrals or integers that are given names by a user. The use of enum in C to name the integer values makes the entire program easy to learn, understand, and maintain by the same or even different programmer.
An enumeration is a data type that consists of a set of named values that represent integral constants, known as enumeration constants. An enumeration is also referred to as an enumerated type because you must list (enumerate) each of the values in creating a name for each of them.
A key distinction between unscoped enumerations and the scoped kind (enum class
), is that the former implicitly convert to their underlying type, whereas the latter do not. Since you are interested in how the type_traits
solution would look, you can check (not entirely tested, may not be SFINAE friendly):
static_assert(std::is_enum<TEvent>::value, "Must be a scoped enum!");
static_assert(!std::is_convertible<TEvent, typename std::underlying_type<TEvent>::type>::value,
"Must be a scoped enum!");
If AVR-GCC has an underlying_type
intrinsic, then you need only supplement the is_convertible
trait (which is even implementable in C++03).
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