在 C++ 中静态区分枚举和枚举类?

Sma*_*ft2 8 c++ enums enumeration static-assert enum-class

我有一个事件处理程序类,它使用模板参数来设置事件类型。我想将这些事件类型强制为一字节大小的枚举类。针对大小的静态断言不是问题,但我无法在网上找到有关如何静态区分enumenum class 的信息

我现在的解决方案是使用C++ 前端实现语法扩展来断言枚举,然后断言正确的大小。在大多数平台上这是有效的,因为枚举使用int类型(通常大于一个字节)。

但这会导致稍微误导性的错误消息。我喜欢彻底。

我可以做哪些检查来传递类枚举,但会因常规的旧枚举而失败?


我不能使用type_traits,因为我使用的编译器(avr-gcc)不支持它。然而type_traits,当需要增加时,我会不断实施我自己的。因此,有关解决方案的任何提示type_traits仍然有用!


最小的例子:

// 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!");
};
Run Code Online (Sandbox Code Playgroud)

用法:

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
Run Code Online (Sandbox Code Playgroud)

目标:

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
Run Code Online (Sandbox Code Playgroud)

Sto*_*ica 6

无作用域枚举和作用域类型 ( enum class)之间的一个关键区别在于,前者隐式转换为其基础类型,而后者则不会。由于您对type_traits解决方案的外观感兴趣,您可以检查(未完全测试,可能对 SFINAE 不友好):

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!");
Run Code Online (Sandbox Code Playgroud)

如果 AVR-GCC 有一个underlying_type内在的,那么你只需要补充is_convertibletrait(它甚至可以在 C++03 中实现)。