【问题标题】:Why is there no overload for printing `std::byte`?为什么打印 `std::byte` 没有过载?
【发布时间】:2021-10-29 19:24:56
【问题描述】:

以下代码在 C++20 中无法编译

#include <iostream>
#include <cstddef>

int main(){ 
    std::byte b {65};
    std::cout<<"byte: "<<b<<'\n';// Missing overload
}

在C++17中添加std::byte时,为什么没有对应的operator&lt;&lt;重载打印呢?我也许可以理解不打印容器的选择,但为什么不std::byte?它试图充当原始类型,我们甚至为std::string、最近的std::string_view也许是最相关的 std::complexstd::bitset 本身提供了重载.

还有std::hex和类似的修饰符,所以默认打印0-255应该不是问题。

这只是疏忽吗? operator&gt;&gt;std::bitset 有呢,一点都不小。

编辑:发现甚至可以打印std::bitset

【问题讨论】:

  • 也许对于它应该格式化为字符还是整数存在分歧。在我看来,如果不是为您做出选择,而是由您决定,那么它作为一种类型会更灵活。
  • @PatrickRoberts 也许,但std::byte 的意义不是unsigned char,所以我不希望有一个角色。也许根本没有必要。

标签: c++ stdout c++20 string-view std-byte


【解决方案1】:

来自paper on std::byte (P0298R3):(强调我的)

设计决策

std::byte 不是整数也不是字符

这里的主要动机是使 byte 成为一种独特的类型——通过利用类型系统来提高程序安全性。这导致std::byte 的设计不是整数类型,也不是字符类型。它是一个与众不同的 用于访问最终构成对象存储的位的类型。

因此,它不需要隐式转换/解释为 char 或任何整数类型,因此不能使用 std::cout 打印,除非显式转换为所需的类型。

此外,this question might help

【讨论】:

  • 好的,我理解不是整数或字符的意义,但std::cout&lt;&lt;std::to_integer&lt;int&gt;(b); 仍然很难看。任何使用内存的工具至少能够进行十六进制转储。因此打印std::byte 不应该是一门火箭科学,毕竟它只是“字节”,这应该是重点。因此,将上面的 sn-p 包装成 opetaror&lt;&lt;std::hexstd::binary 修饰符就是以所有合理格式打印字节所需的一切。
  • 不提供该功能不是“避免为用户做出选择”,它只是乏味,不太友好,并且违背了std::byte提高代码可读性和安全性的目的。无论如何,这可能是我得到的最佳答案,如果没有其他结果,我会再等一会儿并接受它。
  • [对长 cmets 感到抱歉] 此外,我觉得“它是一种用于访问最终构成对象存储的位的独特类型。”并且打印std::bitset 的能力强烈地使所提出的论点无效。
  • @Quimby 没有人将std::bitset 误认为是文本,他们也不会将其误认为是您可以进行算术运算的东西。 提供操作可以提高类型安全性
  • @Quimby 您写的是std::cout&lt;&lt;std::to_integer&lt;int&gt;(b);,但我认为(标准背后的理由)的重点是std::cout&lt;&lt;std::to_char(b); 的可能性相同。似乎这个想法是std::byte 可以是数字、字符、数字的一部分、字符或其他类型或数据。
【解决方案2】:

std::byte 用于访问原始数据。为了允许我用实际上说“这是原始且未解析的”的东西来替换遍布代码库的该死的uint8_t,而不是可能被误解为 C 字符串的东西。

下划线:std::byte 不是“试图成为原始人”,它代表的东西甚至更少——原始数据。

它的实现方式主要是 C++ 和编译器实现的一个怪癖(“原始”类型的布局规则比结构或类简单得多)。

这种事情主要出现在低级代码中,老实说,不应该使用打印。 有时是不可能的

例如,我的用例是通过 I2C(或 RS485)接收原始字节并将其解析为帧,然后将其放入 struct。为什么我要在实际数据上序列化原始字节?我几乎可以立即访问数据?

总结一下这个有点粗鲁的答案,为std::byte 提供运算符重载以与iostream 一起使用违背了这种类型的意图。

尽可能在代码中表达意图是现代编程的重要原则之一。

【讨论】:

  • “这种事情主要出现在低级代码中,老实说,不应该使用打印。有时是不可能的。”这看起来好像低级程序员将被强制打印他们的字节,如果它们是可打印的。我的意思是,如果不应该使用打印,您不会只是……不使用它吗?为什么一定要直接不存在
  • @JohnKugelman 你假设每个人都知道他们在做什么;)我宁愿到处拿走这些工具。
  • 打印出变量的值(或数据缓冲区的内容)是一种相当常见的低级代码调试技术,不是吗?支持它似乎很有用。
  • “我为什么要在实际数据上序列化原始字节”您不是已经通过将原始流划分为std::bytes 来做到这一点了吗?为什么不改为std::bitset?这将更原始,更接近 I2C 的本质。出于好奇,当您启动调试器并将鼠标悬停在std::byte 变量上时,您希望看到什么? 【或(gdb ) p byte】你想看什么?我当然不会对“这是原始且未解析的”感到高兴。
  • @JanDorniak 当然,我现在很乐意使用 unsigned char 作为字节。我只是好奇为什么无法打印std::byte,让我大吃一惊。
猜你喜欢
  • 2021-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-08
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
相关资源
最近更新 更多