是否可以确定枚举是否是强类型的?

Scu*_*der 8 c++ enums type-traits c++11

C++ 11为我们如何处理枚举引入了两个不同的补充:一个使它们成为范围的选项,以及一个使它们键入的选项.所以现在我们有四种不同的枚举子类型:

enum Old {};
enum Typed : int8_t {};
enum class Scoped {};
enum class TypedScoped : int8_t {};
Run Code Online (Sandbox Code Playgroud)

这个问题询问如何确定枚举是否作用域.我想知道如何确定是否键入枚举.


附加信息

我使用Qt框架,它提供了QDataStream以便携式跨平台方式序列化/反序列化数据的类.显然,为了使结果数据流可移植,您必须以固定长度的形式存储所有整数.这也包括枚举.回到当天,我制作了几个辅助宏来定义枚举的序列化/反序列化,方法是将它们转换为具有固定(用户指定)长度的整数:

#define SC_DECLARE_DATASTREAM_WRITE_OPERATOR(_TYPE) \
    QDataStream &operator<<(QDataStream &stream, _TYPE v);

#define SC_DECLARE_DATASTREAM_READ_OPERATOR(_TYPE) \
    QDataStream &operator>>(QDataStream &stream, _TYPE &v);

#define SC_DECLARE_DATASTREAM_OPERATORS(_TYPE) \
    SC_DECLARE_DATASTREAM_WRITE_OPERATOR(_TYPE) \
    SC_DECLARE_DATASTREAM_READ_OPERATOR(_TYPE)

#define SC_DEFINE_DATASTREAM_ENUM_WRITE_OPERATOR(_TYPE, _LEN) \
    QDataStream &operator<<(QDataStream &stream, _TYPE v) \
{ \
    qint ## _LEN t = v; \
    static_assert(sizeof(t) >= sizeof(v), "Increase length"); \
    stream << t; \
    return stream; \
    }

#define SC_DEFINE_DATASTREAM_ENUM_READ_OPERATOR(_TYPE, _LEN) \
    QDataStream &operator>>(QDataStream &stream, _TYPE &v) \
{ \
    qint ## _LEN t {0}; \
    static_assert(sizeof(t) >= sizeof(v), "Increase length"); \
    stream >> t; \
    if(stream.status() == QDataStream::Ok) \
    v = static_cast<_TYPE>(t); \
    return stream; \
    }

#define SC_DEFINE_DATASTREAM_ENUM_OPERATORS(_TYPE, _LEN) \
    SC_DEFINE_DATASTREAM_ENUM_WRITE_OPERATOR(_TYPE, _LEN) \
    SC_DEFINE_DATASTREAM_ENUM_READ_OPERATOR(_TYPE, _LEN)
Run Code Online (Sandbox Code Playgroud)

现在C++ 11允许指定底层枚举类型,我可以简化上面提到的宏:

#define SC_DEFINE_DATASTREAM_TYPED_ENUM_WRITE_OPERATOR(_TYPE) \
    QDataStream &operator<<(QDataStream &stream, _TYPE v) \
{ \
    const std::underlying_type<_TYPE>::type t {static_cast<std::underlying_type<_TYPE>::type>(v)}; \
    stream << t; \
    return stream; \
    }

#define SC_DEFINE_DATASTREAM_TYPED_ENUM_READ_OPERATOR(_TYPE) \
    QDataStream &operator>>(QDataStream &stream, _TYPE &v) \
{ \
    std::underlying_type<_TYPE>::type t {0}; \
    stream >> t; \
    if(stream.status() == QDataStream::Ok) \
    v = static_cast<_TYPE>(t); \
    return stream; \
    }
Run Code Online (Sandbox Code Playgroud)

但是,如果用户意外地将new(*_TYPED_*)宏用于未指定其基础类型的枚举,那将破坏可移植性的保证,因为在不同平台上编译相同的代码可能会产生不同的底层类型,因此会产生不同的整数长度.序列化/反序列化代码.我需要的是static_assert在代码中添加一个代码,如果枚举在声明时没有强类型,这将打破编译过程.

Joh*_*nck 0

回答标题问题:不,不可能知道枚举是否具有显式基础类型。

即使有,它也不能解决您的实际问题,这更像是“如何知道枚举类型是否具有固定大小?”

想象一下这个简单的例子:

enum class Foo : long {};
Run Code Online (Sandbox Code Playgroud)

在某些系统上,这将是 32 位,而在其他系统上,这将是 64 位。因此,即使某种机制让您发现它具有显式类型,它也不会帮助您,因为大小不可移植。