Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Statically distinguish between an enum and an enum class in C++?

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
like image 891
Smartskaft2 Avatar asked Jun 15 '20 10:06

Smartskaft2


People also ask

What is the difference between an enum and an enum class?

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).

Is enum static C#?

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.

What is enum in C language?

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.

What is enum and enumerations?

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.


1 Answers

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).

like image 93
StoryTeller - Unslander Monica Avatar answered Sep 21 '22 14:09

StoryTeller - Unslander Monica