c – 将enum类变量重新解释_cast到底层类型的引用是否安全?

前端之家收集整理的这篇文章主要介绍了c – 将enum类变量重新解释_cast到底层类型的引用是否安全?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我看到reinterpret_cast用来应用增量到枚举类,我想知道这个用法在标准C中是否可以接受.
enum class Foo : int8_t
{
    Bar1,Bar2,Bar3,Bar4,First = Bar1,Last = Bar4
};

for (Foo foo = Foo::First; foo <= Foo::Last; ++reinterpret_cast<int8_t &>(foo))
{
    ...
}

我知道转换为基类的引用是平凡的类的安全.但是,由于枚举类不是事件隐式转换为其底层类型,我不知道上述代码是否以及如何保证在所有编译器中都可以工作.任何线索?

解决方法

如果你真的想迭代它的值,你可能需要为你的枚举重载运算符:
Foo& operator++( Foo& f )
{
    using UT = std::underlying_type< Foo >::type;
    f = static_cast< Foo >( static_cast< UT >( f ) + 1 );
    return f;
}

并使用

for (Foo foo = Foo::First; foo != Foo::Last; ++foo)
{
    ...
}

为了回答是否允许reinterpret_cast的问题,它全部从5.2.10 / 1开始:

5.2.10 Reinterpret cast [expr.reinterpret.cast]

1 The result of the expression reinterpret_cast<T>(v) is the result of converting the expression v to type T. If T is an lvalue reference type or an rvalue reference to function type,the result is an lvalue; if T is an rvalue reference to object type,the result is an xvalue; otherwise,the result is a prvalue and the lvalue-to-rvalue (4.1),array-to-pointer (4.2),and function-to-pointer (4.3) standard conversions are performed on the expression v. Conversions that can be performed explicitly using reinterpret_cast are listed below. No other conversion can be performed explicitly using reinterpret_cast.

(强调我的)

使用引用的重新解释是基于5.2.10 / 11的指针:

11 A glvalue expression of type T1 can be cast to the type “reference to T2” if an expression of type “pointer to T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_cast. The result refers to the same object as the source glvalue,but with the specified type. [ Note: That is,for lvalues,a reference cast reinterpret_cast<T&>(x) has the same effect as the conversion *reinterpret_cast<T*>(&x) with the built-in & and * operators (and similarly for reinterpret_cast<T&&>(x)). — end note ] No temporary is created,no copy is made,and constructors (12.1) or conversion functions (12.3) are not called.

这从哪个转变了问题:

reinterpret_cast<int8_t&>(foo)

这是否合法?

*reinterpret_cast<int8_t*>(&foo)

下一站是5.2.10 / 7:

7 An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of type “pointer to T1” is converted to the type “pointer to cv T2”,the result is static_cast<cvT2*>(static_cast<cvvoid*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1,or if either type is void. Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.

给定3.9 / 9,int8_t和你的枚举类型是标准布局类型,问题现在转换为:

*static_cast<int8_t*>(static_cast<void*>(&foo))

这是你失败的地方. static_cast在5.2.9中定义,没有什么可以使上述合法 – 实际上5.2.9 / 5是一个明确的提示,这是非法的.其他条款没有帮助:

> 5.2.9 / 13要求T * – > void * – > T *其中T必须相同(省略cv)
> 5.2.9 / 9和5.2.9 / 10不是关于指针,而是关于值
> 5.2.9 / 11是关于类和类层次结构
> 5.2.9 / 12是关于类成员的指针

我的结论是你的代码

reinterpret_cast<int8_t&>(foo)

不合法,其行为不是由标准定义的.

另请注意,上述5.2.9 / 9和5.2.9 / 10负责将代码合法化,我在初始答案中给出了代码,您仍然可以在顶部找到该代码.

猜你在找的C&C++相关文章