为什么std::( i)ostream将signed/unsigned char视为文本而不是整数?

11 c++ language-lawyer

此代码不执行它应该执行的操作:

#include <iostream>
#include <cstdint>

int main()
{
    uint8_t small_integer;
    std::cin >> small_integer;
    std::cout << small_integer;
}
Run Code Online (Sandbox Code Playgroud)

原因很简单:uint8_t是typedef for unsigned char和streams将此类型视为文本:
Visual C++ 2015实现

template<class _Traits> inline
    basic_istream<char, _Traits>& operator>>(
        basic_istream<char, _Traits>& _Istr, unsigned char& _Ch)
    {    // extract an unsigned char
    return (_Istr >> (char&)_Ch);
    }
Run Code Online (Sandbox Code Playgroud)

和类似的代码与强制转换charoperator <<.

我的问题:

  1. 这种行为(流操作符将signed/unsigned char视为字符类型而不是整数)是标准所要求的吗?如果是的话:
    1. 这种违反直觉的语义背后的理由是什么?
    2. 如果这被视为缺陷,是否有建议改变这种语义?

我应该添加一些解释为什么我认为它违反直觉.虽然类型名称包含单词char,但是signed或者unsigned部分指定特定的整数语义,并且这些类型通常用作字节大小的整数.甚至标准定义int8_t/ uint8_t通过它们.

UPD:问题是关于流媒体运营商重载的行为unsigned charsigned char.

小智 3

标准 (n3797) 规定如下:

\n\n
\n

27.7.2.2.3 basic_istream::运算符>>

\n
\n\n
template<class charT, class traits> \nbasic_istream<charT,traits>& operator>>(basic_istream<charT,traits>& in, charT& c);\n\ntemplate<class traits> \nbasic_istream<char,traits>& operator>>(basic_istream<char,traits>& in, unsigned char& c);\n\ntemplate<class traits> \nbasic_istream<char,traits>& operator>>(basic_istream<char,traits>& in, signed char& c);\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

12 E\xef\xac\x80ects:行为类似于 in 的格式化输入成员(如 27.7.2.2.1 中所述)。构造哨兵对象后,将从in 中提取字符(如果可用)并将其存储在 c 中。否则,该函数调用 in.setstate(failbit)。

\n\n

27.7.3.6.4 字符插入器函数模板

\n
\n\n
// specialization \ntemplate<class traits> \nbasic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, char c); \n\n// signed and unsigned \ntemplate<class traits> \nbasic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, signed char c); \n\ntemplate<class traits> \nbasic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, unsigned char c); \n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

1 E\xef\xac\x80ects:表现为 out 的格式化输出函数(27.7.3.6.1)。构造一个字符序列 seq。如果 c 的类型为 char 并且流的字符类型不是 char,则seq 包含 out.widen(c); 否则 seq 由 c 组成。确定 seq 的填充,如 27.7.3.6.1 中所述。将 seq 插入到 out 中。调用 os.width(0)。

\n
\n\n

所以第一个问题的答案是:是的,标准要求 和 的operator >>行为与、和operator <<完全相同,即它们读/写单个字符,而不是整数。不幸的是,标准没有解释原因。我希望有人能阐明2和3。charunsigned charsigned char

\n