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

时间:2020-06-15 10:11:04

标签: c++ enums enumeration static-assert enum-class

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

我现在的解决方案是使用C++ front-end implements syntactic extensions声明枚举,然后声明正确的大小。在大多数平台上,这是可行的,因为枚举使用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!");
};

用法:

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

目标:

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

1 个答案:

答案 0 :(得分: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!");

如果AVR-GCC具有underlying_type内在函数,则只需补充is_convertible特性(甚至可以在C ++ 03中实现)。