为什么打印 `std::byte` 没有过载?

Qui*_*mby 17 c++ stdout string-view c++20 std-byte

以下代码不能在 C++20 中编译

#include <iostream>
#include <cstddef>

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

std::byteC++17什么时候加入的,为什么没有对应的operator<<重载打印呢?我也许可以理解不打印容器的选择,但为什么不std::byte呢?它试图充当原始类型,我们甚至有 的重载std::string,最近的std::string_view也许是最相关的 std::complex并且std::bitset它本身可以被打印。

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

这只是疏忽吗?怎么样operator>>std::bitset有它,它根本不是微不足道的。

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

Ruk*_*uks 19

来自(P0298R3)std::byte论文:(强调我的)

设计决策

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

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

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

此外,这个问题可能会有所帮助

  • @Quimby 你写了 `std::cout&lt;&lt;std::to_integer&lt;int&gt;(b);` 但我认为(标准背后的原理)的重点是 `std::cout&lt;&lt;std::to_char( b);` 的可能性相同。似乎这个想法是 `std::byte` 可以是一个数字、一个字符、一个数字的一​​部分、一个字符或其他一些类型或数据。 (10认同)
  • 不提供该功能并不是“避免为用户做出选择”,它只是乏味,不那么用户友好,并且违背了 `std::byte` 提高代码可读性和安全性的目的。无论如何,这可能是我得到的最佳答案,如果没有其他问题出现,我会再等一会儿并接受它。 (7认同)
  • @Quimby 没有人将 `std::bitset` 误认为是文本,也不会将其误认为是可以进行算术运算的东西。*不*提供操作可以提高类型安全性 (5认同)
  • 好吧,我明白不是整数或字符的要点,但 `std::cout&lt;&lt;std::to_integer&lt;int&gt;(b);` 仍然丑陋。任何使用内存的工具至少都能够进行十六进制转储。因此,打印 `std::byte` 不应该是一个火箭科学,它毕竟只是“字节”,这应该是重点。因此,将上面的代码片段包装到 `opetaror&lt;&lt;` 和 `std::hex`、`std::binary` 修饰符中就是以所有合理格式打印字节所需的一切。 (2认同)
  • [抱歉发表了很长的评论]此外,我觉得“这是一种独特的类型,用于访问最终构成对象存储的位。” 并且打印“std::bitset”的能力使所提供的参数强烈无效。 (2认同)
  • @Caleth,@DanielLangr 我并不是反对缺少算术,只是反对 IO。例如,如何通过 `bitset&lt;12&gt; x; 接受 `110` cin&lt;&lt;x;` 可以,但被认为不适合 `std::byte`? (2认同)
  • C++ 选择与 70 年的计算相悖,其中一个字节被理解为一组位(其大小主要定为 8),并且根据二进制枚举系统具有可识别的整数值。 (2认同)

Jan*_*iak 8

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

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

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

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

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

总结一下这个有点啰嗦的答案,提供操作符重载std::byte来处理与iostream这种类型的意图背道而驰。

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

  • 打印出变量的值(或数据缓冲区的内容)是低级代码的一种相当常见的调试技术,不是吗?看来支持这一点很有用。 (3认同)
  • “这种事情主要出现在低级代码中,老实说,不应该使用打印。有时这是不可能的。” 这读起来就好像低级程序员将“被迫”打印他们的字节(如果它们是可打印的)。我的意思是,如果不应该使用打印,您难道不......不使用它吗?为什么它必须直接*不存在*? (2认同)
  • @JanDorniak 当然,我现在很乐意使用“unsigned char”作为字节。我只是好奇为什么 `std::byte` 无法打印,这让我大吃一惊。 (2认同)