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
在代码中添加一个代码,如果枚举在声明时没有强类型,这将打破编译过程.
回答标题问题:不,不可能知道枚举是否具有显式基础类型。
即使有,它也不能解决您的实际问题,这更像是“如何知道枚举类型是否具有固定大小?”
想象一下这个简单的例子:
enum class Foo : long {};
Run Code Online (Sandbox Code Playgroud)
在某些系统上,这将是 32 位,而在其他系统上,这将是 64 位。因此,即使某种机制让您发现它具有显式类型,它也不会帮助您,因为大小不可移植。
归档时间: |
|
查看次数: |
246 次 |
最近记录: |