On Fri, Oct 2, 2020 at 1:31 PM Hadriel Kaplan via Boost
On Oct 2, 2020, at 6:08 AM, Andrzej Krzemienski
wrote: My only complaint is that unsigned char and signed char (and thus uint8_t and int8_t) are streamed as their char values, and thus as their unadorned ASCII characters. Since they can be non-printable values, I consider this behavior undesirable.
But should this complaint target PFR or C++ in general? This program outputs "4". What is broken is that `uint8_t` is an alias on `unsigned char` but as humans we expect something different from `unsigned char` and from `uint8_t`. I think PFR makes the right choice here: stream uint8_t the same way as if a user streamed it manually with `std::cout << u`. It is consistent in replicating the error-prone behavior.
Of course std::ostream in general has this problem, but we’re not talking about what it does - we’re talking instead about what PFR does. :)
And by that I mean, to me, how PFR chooses to stringify char-type struct members is an implementation detail of PFR and not an API contract to the user. The public API of PFR offers a streaming operator, obviously, but as far as the user knows you could choose to use any number of ways to achieve that under-the-hood for char-types.
As a user, I neither know nor care how it achieves that - I only care that the output is usable. Right now, the output isn’t usable in what I would argue is the far more common use-case. But of course I could be wrong; I’m not claiming to have crystal ball.
(Also, on a side-note: why shouldn’t Boost provide such things _without_ repeating mistakes in the standard library? Can we not use hindsight and real-world results to provide something better than the standard libraries?)
I think it is better to have the error-prone behavior consistent in all places than to apply fixes at random places with dubious effect:
``` struct Encoding { char alphabetLetter; int ocurrences; };
Encoding e {'a', 112}; ``` I really expect that to be output as "a 112”.
You shouldn’t want it to, imo. One of the big benefits of using PFR is you can stream structs out for debugging/logging. It’s completely useless to stream a char as a char for debugging, because the whole point is you don’t know what’s in the char, which is why you’re debugging it. *You* happen to know (or think) the `alphabetLetter` is a printable character because you named it that and are using it for that - but really it’s just a `char`, and despite being called `char` fundamentally nothing requires them to be ASCII characters (as you well know :)
But let’s assume you really do want `char` types to print ‘a’ - is that the common use-case expectation, or the less-common one?
Generating non-printable output doesn’t make any sense, for what I would argue are the most common use cases.
-hadriel
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
std::ostream already gives you the tools to customize the output of
types by overloading operator<<. If you're having trouble debugging
char values in your program, you can write an overload to print them
however you please. The advantage of this approach is that it changes
the output of all of your chars, not only those contained in
aggregates.
My expectation as a user of the aggregate operator<< would be that
it's some composition of the operator<