【问题标题】:C-style cast of enum class to reference of underlying type char枚举类的 C 样式转换为底层类型 char 的引用
【发布时间】:2020-06-10 22:04:28
【问题描述】:

这是合法的 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 &gt;&gt; static_cast&lt;std::underlying_type_t&lt;ECode&gt;&amp;&gt;(aCode),这似乎是不合法的(“不能转换为不相关类型的引用”。)

但是,这条非常相似的行是合法的,并且是我的 C 风格转换应该与以下内容相同:

return aIn >> *static_cast<char*>(static_cast<void*>(&aCode))

【问题讨论】:

  • @Quentin 有趣。由于 5 岁的答案是“这从标准中不清楚”,我仍然希望获得更新 C++ 版本的答案。我将删除 C++14 标记。
  • 我建议对现有问题给予赏金,因为我认为这方面没有任何改变(无论如何我都会对这段代码皱眉 - 为什么不提取到char,然后正确转换为ECode 最后分配?它会超级快)
  • 这个问题与另一个问题的不同之处在于,通过类型char 访问对象永远不会违反严格的别名规则。但我没有看到任何与枚举类型及其基础类型的值表示相关的保证。
  • @AsteroidsWithWings 这正是我拥有的代码,但这仍然引发了问题。我喜欢(至少知道合法的)单行代码,即使只是为了开玩笑,即使他们没有通过代码审查;)

标签: c++ casting language-lawyer enum-class


【解决方案1】:

正如在 cmets 中所指出的,不存在严格的别名冲突,因为 char 可以为任何类型设置别名。

在实践中,我怀疑任何真正的编译器会做除了“显而易见的”实现之外的任何事情,即赋予枚举与底层类型相同的大小和表示。在这种情况下,您的 reinterpret_cast 将被明确定义并按预期运行。

但是标准(从 C++17 开始)似乎并不能保证这一点。

据我所知,它只指定了任何基础类型的值都可以存储在枚举对象中,并且static_cast可以无损地用于基础类型范围内的值。

a language lawyer question here 关于sizeof(ECode) == sizeof(char) 是否必须成立,尽管答案似乎说“标准实际上并没有这么说,但他们可能是认真的”。

但即使大小相同,也没有代表保证,例如这些位可以以不同的顺序存储,static_cast 会转换这些位。

在 [basic.fundamental] 中,它指定整数类型的表示,它甚至有一个明确的脚注说明枚举不是整数类型。

【讨论】:

  • enum class byte : unsigned char {} ; 的 C++17 定义似乎暗示大小和表示必须与 unsigned char 相同。我想知道这是否可以推广,但可能不是(他们在这里扩展标准吗?:))。我也想知道为什么他们不只是写他们的意思......
  • @FelixDombek 似乎某处存在疏忽(在标准中并不少见),例如也许写std::byte插件的人没有意识到枚举大小的规格不足
猜你喜欢
  • 2020-01-04
  • 1970-01-01
  • 2015-08-04
  • 2010-11-10
  • 2014-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-14
相关资源
最近更新 更多