public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jonathan Wakely <jwakely@redhat.com>
To: "Théo Papadopoulo" <papadopoulo@gmail.com>
Cc: "libstdc++" <libstdc++@gcc.gnu.org>
Subject: Re: operator<< and int8_t and uint8_t types....
Date: Mon, 23 Oct 2023 12:45:01 +0100	[thread overview]
Message-ID: <CACb0b4ngRWaOe_O7v5EavxYK5y34CQ7=LoaOdnrDNVxNquH3UA@mail.gmail.com> (raw)
In-Reply-To: <32b868eb-2569-471c-8f19-aac7fc362c42@gmail.com>

On Mon, 23 Oct 2023 at 12:36, Théo Papadopoulo <papadopoulo@gmail.com> wrote:
>
>      Hi,
>
> I suspect that this will probably receive an answer "this is the
> intended/normal/expected  behavior",


Correct.

> but from what I saw on the internet
> this is a kind of gray area in the standard

Not really.

> and I did not found any
> (even closed) report on bugzilla, so I thought of asking here.
>
> Currently, printing a int8_t of uint8_t number with operator<< basically
> prints it as a (u)char. I think this is very unfortunate and is somewhat
> deceptive to
> users which expect a "int" like behavior.

But int8_t is not an int, it's a typedef for an unspecified 8-bit
integral type, typically signed char (or potentially, but unlikely,
char, if that happens to be signed). The behaviour when printing
signed char is 100% specfied, there is no wriggle room for doing
anything else.

> #include <iostream>
> #include <cstdint>
>
> namespace std {
>
>      std::ostream& operator<<(std::ostream& os,const int8_t v) {
>          return os << static_cast<int>(v);
>      }
>
>      std::ostream& operator<<(std::ostream& os,const uint8_t v) {
>          return os << static_cast<int>(v);
>      }
> }
>
> int main() {
>      std::int8_t a  = 65;
>      std::uint8_t b = 66;
>      char         c = 'c';
>      std::cerr << a << ' ' << b << ' ' << c << std::endl;
> }
>
> Without the operator<< overloads: this code prints:
>
> A B c
>
> whereas I think a programmer would expect to see:
>
> 65 66 c
>
> which is what is obtained with the overloads.
>
> There is an old and extended discussion on stack overflow on the
> subject, in which from some comment it seems that
> it is the promotion to int vs the conversion to char that plays a role
> here (and that gcc like many over compiler favors the char
> conversion over the int promotion, but I'm not so sure about the
> validity of this discussion).

The standard specifies exactly how integer promotions work. There is
nothing any compiler can do to favour one promotion or another, it's
dictated by the standard.

But that's irrelevant here, there is no promotion. The standard
requires the following overloads which define how signed char and
unsigned char are printed:

template<class traits>
basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&,
signed char);
template<class traits>
basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&,
unsigned char);

The standard requires int8_t and uint8_t to be typedefs, not distinct
types. On most platforms, there are no integral types with exactly 8
bits except for char, signed char and unsigned char, and since C++20,
char8_t. So int8_t and uint8_t MUST be typedefs for one of those. How
those are printed with iostreams is clearly specified by the standard.


> Certainly from the user's perspective, one would expect to see and
> integer value and not a char... and it does not look very difficult to do.

The standard already says how to print those types, adding a more
specialized overload that only works for std::ostream (and not
std::basic_ostream<char, acme::traits<char>>) would be a breaking
change, and very surprising to all the users who do actually know how
this works.


  reply	other threads:[~2023-10-23 11:45 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-23 11:36 Théo Papadopoulo
2023-10-23 11:45 ` Jonathan Wakely [this message]
2023-10-23 11:53   ` Jonathan Wakely
2023-10-23 12:01     ` Jonathan Wakely

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CACb0b4ngRWaOe_O7v5EavxYK5y34CQ7=LoaOdnrDNVxNquH3UA@mail.gmail.com' \
    --to=jwakely@redhat.com \
    --cc=libstdc++@gcc.gnu.org \
    --cc=papadopoulo@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).