uint8_t not getting output to cout?

Hello. Please see the following simple code:

#include <cstdint>
#include <cstdio>
#include <iostream>
int main()
{
    std::uint16_t y = 2019;
    std::uint8_t m = 2, d = 13;
    std::printf("%d-%d-%d\n", y, m, d);
    std::cout << y << '-' << m << '-' << d << std::endl;
    std::cout << int(y) << '-' << int(m) << '-' << int(d) << std::endl;
}

The above code outputs:

2019-2-13
2019- -
2019-2-13

The character on the second line after the hyphen is Unicode codepoint 0x0002!

The same behaviour happens with both Clang 6 and GCC 7.3.0 available
by default on my Kubuntu Bionic LTS system.

What is wrong with expecting std::cout to properly print uint8_t when
printf can do it?

Presumably, on your system, uint8_t is typef'd to "char".

Try changing the 2 to 65 and see if you get 'A'. And if you change the
13 to 10 you'll get a newline after the 2nd '-'.

Dear me, you're right! But this is horrible! I am using uint8_t
importing it from the “stdint” library because I think of it as an
integer! Is there no way to get this treated as an integer?!

(BTW D has a type `byte` for 8-bit integers as distinct from `char`
for 8-bit characters: Types - D Programming Language)

It *is* an integer. And so is the '-' when you write:

std::cout << int(y) << '-' << int(m) << '-' << int(d) << std::endl;

The problem is more that C and C++ don't have a proper character type.
"char" is just a small integer. The only reason this line of code dos
what you expect is that someone decided to make operator<<(ostream&,
char) copy the bits of, say 0x41 directly to the stream buffer while
operator<<(ostream&, short) and operator<<(ostream&, int) convert
0x0041 or 0x00000041 to the string "65" before adding it to the stream
buffer.

printf() "works" because you explicitly asked it to convert all the
arguments to decimal strings by writing %d for the char arguments
rather than %c.

It would probably have been better design for the C++ library to give
operator<< similar behaviour for all of char, short, and int make you
write...

std::cout << y << "-" << m << "-" << d << std::endl;

... to get what you want, but someone wanted to save a couple of
memory loads and branches.

That is one of the things that Java and C# and D improve on. But C and
anything that wants to remain compatible with C is stuck with it.