枚举 class 的 C 风格转换为基础类型 char 的引用
C-style cast of enum class to reference of underlying type char
这是合法的 C++ (>=14),导致 char
被读取并保存到 aCode
中吗?
enum class ECode : char { Code1 = 'a' };
std::istream& operator>>(std::istream& aIn, ECode& aCode)
{
return aIn >> (std::underlying_type_t<ECode>&)aCode;
}
我更喜欢 return aIn >> static_cast<std::underlying_type_t<ECode>&>(aCode)
,这似乎是不合法的 ("cannot cast to reference of unrelated type".)
然而,这条非常相似的行是合法的,并且是我的 C 风格转换应该相同的行:
return aIn >> *static_cast<char*>(static_cast<void*>(&aCode))
如评论中所述,不存在严格的别名违规,因为 char
可以为任何类型起别名。
实际上,我怀疑任何真正的编译器都会做除 "obvious" 实现之外的任何事情,即为枚举提供与基础类型相同的大小和表示形式。在这种情况下,您的 reinterpret_cast
将被明确定义并按预期运行。
然而,标准(自 C++17 起)似乎并不能保证这一点。
据我所知,它只是规定了底层类型的任何值都可以存储在枚举对象中,并且static_cast
可以无损地用于底层类型范围内的值.
关于 sizeof(ECode) == sizeof(char)
是否必须成立,有 a language lawyer question here,虽然答案似乎是 "the standard doesn't actually say so but they probably meant it"。
但即使大小相同,也没有代表保证,例如这些位可以以某种不同的顺序存储,并且 static_cast
转换这些位。
在指定整数类型表示的[basic.fundamental]中,它甚至有一个明确的脚注说枚举不是整数类型。
这是合法的 C++ (>=14),导致 char
被读取并保存到 aCode
中吗?
enum class ECode : char { Code1 = 'a' };
std::istream& operator>>(std::istream& aIn, ECode& aCode)
{
return aIn >> (std::underlying_type_t<ECode>&)aCode;
}
我更喜欢 return aIn >> static_cast<std::underlying_type_t<ECode>&>(aCode)
,这似乎是不合法的 ("cannot cast to reference of unrelated type".)
然而,这条非常相似的行是合法的,并且是我的 C 风格转换应该相同的行:
return aIn >> *static_cast<char*>(static_cast<void*>(&aCode))
如评论中所述,不存在严格的别名违规,因为 char
可以为任何类型起别名。
实际上,我怀疑任何真正的编译器都会做除 "obvious" 实现之外的任何事情,即为枚举提供与基础类型相同的大小和表示形式。在这种情况下,您的 reinterpret_cast
将被明确定义并按预期运行。
然而,标准(自 C++17 起)似乎并不能保证这一点。
据我所知,它只是规定了底层类型的任何值都可以存储在枚举对象中,并且static_cast
可以无损地用于底层类型范围内的值.
关于 sizeof(ECode) == sizeof(char)
是否必须成立,有 a language lawyer question here,虽然答案似乎是 "the standard doesn't actually say so but they probably meant it"。
但即使大小相同,也没有代表保证,例如这些位可以以某种不同的顺序存储,并且 static_cast
转换这些位。
在指定整数类型表示的[basic.fundamental]中,它甚至有一个明确的脚注说枚举不是整数类型。