The following code does not compile in C++20
#include <iostream>
#include <cstddef>
int main(){
std::byte b {65};
std::cout<<"byte: "<<b<<'\n';// Missing overload
}
When std::byte
was added in C++17, why was there no corresponding operator<<
overloading for printing it? I can maybe understand the choice of not printing containers, but why not std::byte
? It tries to act as primitive type and we even have overloads for std::string
, the recent std::string_view
, and perhaps the most related std::complex
, and std::bitset
itself can be printed.
There are also std::hex
and similar modifiers, so printing 0-255 by default should not be an issue.
Was this just oversight? What about operator>>
, std::bitset
has it and it is not trivial at all.
EDIT: Found out even std::bitset
can be printed.
From the paper on std::byte
(P0298R3): (emphasis mine)
Design Decisions
std::byte
is not an integer and not a characterThe key motivation here is to make byte a distinct type – to improve program safety by leveraging the type system. This leads to the design that
std::byte
is not an integer type, nor a character type. It is a distinct type for accessing the bits that ultimately make up object storage.
As such, it is not required to be implicitly convertible/interpreted to be either a char
or any integral type whatsoever and hence cannot be printed using std::cout
unless explicitly cast to the required type.
Furthermore, this question might help.
std::byte
is intended for accessing raw data. To allow me to replace that damn uint8_t
sprinkled all over the codebase with something that actually says "this is raw and unparsed", instead of something that could be misunderstood as a C string.
To underline: std::byte
doesn't "try to be a primitive", it represents something even less - raw data.
That it's implemented like this is mostly a quirk of C++ and compiler implementations (layout rules for "primitive" types are much simpler than for a struct or a class).
This kind of thing is mostly found in low level code where, honestly, printing shouldn't be used. Isn't possible sometimes.
My use case, for example, is receiving raw bytes over I2C (or RS485) and parsing them into frame which is then put into a struct
. Why would I want to serialize raw bytes over actual data? Data I will have access to almost immediately?
To sum up this somewhat ranty answer, providing operator overloads for std::byte
to work with iostream
goes against the intent of this type.
And expressing intent in code as much as possible is one of important principles in modern programming.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With