C++什么时候在输出流operator<<()中加宽字符?
C++ When are characters widened in output stream operator<<()?
在我看来,C++ 标准存在不一致之处,特别是在 C++17 草案 (N4659) 的 §30.7.5.2.4 中,关于何时在输出的格式化输出操作中加宽字符流 (operator<<()
)。完全相同的不一致似乎反映在 en.cppreference.com.
中
首先,假设以下声明:
std::ostream out;
std::wostream wout;
char ch;
wchar_t wch;
const char* str;
const wchar_t* wstr;
然后说
out << ch
不执行字符加宽,
out << str
执行字符加宽,
wout << ch
执行字符加宽,
wout << str
执行字符加宽,
wout << wch
不执行字符加宽,
wout << wstr
执行字符加宽。
第一个也是最明显的不一致是 (6) 不可能为真,因为没有 widen()
函数接受 wchar_t
参数,只有一个接受 char
参数.
第二个(看似)不一致是在(1)和(2)之间。 out << "x"
应该加宽 'x'
,而 out << 'x'
不应该加宽,这对我来说似乎很奇怪。
我是不是误解了标准文本,还是哪里有问题?如果是后者,您知道预期的行为是什么吗?
编辑:显然,这种不一致(如果我是对的)至少从 C++03 (§27.6.2.5.4) 开始就存在于标准中。通过中间标准,文本略有变化,但正如我在上面解释的那样,不一致仍然存在。
看起来标准并不完全正确。大多数问题源于各个操作的批量规范。不是单独处理每个重载,而是一起描述类似的重载,从而导致误导性规范。
我怀疑,尽管如此,任何实施者都难以理解其意图。本质上,当 char
插入到非 char
流中时,需要对字符进行 widen()
ed 以获得流字符类型的字符。此加宽旨在将源字符集中的一个字符映射到流的宽字符集中的一个字符。
请注意,IOStreams 规范假定流中字符的原始概念是独立的实体。自从规范创建(针对 C++1998 版本)以来,文本并没有真正更新,但随着 Unicode 的广泛使用,流中的 "characters" 实际上是编码的字节。虽然流在这个修改后的环境中大部分功能正常,但一些有助于处理 Unicode 字符的灵活性并没有得到真正的正确支持。在 UTF8 字节序列中缺少 "widening" 一个字符可能是其中之一。
如果您觉得流部分中的 inconsistency/incorrectness 值得解决,请提交缺陷报告。关于提交缺陷报告的说明位于 http://isocpp.org。当您确实提出问题时,请考虑提供建议的措辞来纠正问题。由于并不缺乏明确的实际意图,而且可能大多数实现都在做正确的事情,所以我希望这个问题的优先级相当低,如果没有建议的措辞,它不太可能受到太多关注。当然,解决这个问题不会改变预期的行为,例如,将 "widen" char
s 转换为 UTF8 序列:这实际上是对流库的重新设计,它可能是有序的但赢得' 作为缺陷解决的一部分完成。
在我看来,C++ 标准存在不一致之处,特别是在 C++17 草案 (N4659) 的 §30.7.5.2.4 中,关于何时在输出的格式化输出操作中加宽字符流 (operator<<()
)。完全相同的不一致似乎反映在 en.cppreference.com.
首先,假设以下声明:
std::ostream out;
std::wostream wout;
char ch;
wchar_t wch;
const char* str;
const wchar_t* wstr;
然后说
out << ch
不执行字符加宽,out << str
执行字符加宽,wout << ch
执行字符加宽,wout << str
执行字符加宽,wout << wch
不执行字符加宽,wout << wstr
执行字符加宽。
第一个也是最明显的不一致是 (6) 不可能为真,因为没有 widen()
函数接受 wchar_t
参数,只有一个接受 char
参数.
第二个(看似)不一致是在(1)和(2)之间。 out << "x"
应该加宽 'x'
,而 out << 'x'
不应该加宽,这对我来说似乎很奇怪。
我是不是误解了标准文本,还是哪里有问题?如果是后者,您知道预期的行为是什么吗?
编辑:显然,这种不一致(如果我是对的)至少从 C++03 (§27.6.2.5.4) 开始就存在于标准中。通过中间标准,文本略有变化,但正如我在上面解释的那样,不一致仍然存在。
看起来标准并不完全正确。大多数问题源于各个操作的批量规范。不是单独处理每个重载,而是一起描述类似的重载,从而导致误导性规范。
我怀疑,尽管如此,任何实施者都难以理解其意图。本质上,当 char
插入到非 char
流中时,需要对字符进行 widen()
ed 以获得流字符类型的字符。此加宽旨在将源字符集中的一个字符映射到流的宽字符集中的一个字符。
请注意,IOStreams 规范假定流中字符的原始概念是独立的实体。自从规范创建(针对 C++1998 版本)以来,文本并没有真正更新,但随着 Unicode 的广泛使用,流中的 "characters" 实际上是编码的字节。虽然流在这个修改后的环境中大部分功能正常,但一些有助于处理 Unicode 字符的灵活性并没有得到真正的正确支持。在 UTF8 字节序列中缺少 "widening" 一个字符可能是其中之一。
如果您觉得流部分中的 inconsistency/incorrectness 值得解决,请提交缺陷报告。关于提交缺陷报告的说明位于 http://isocpp.org。当您确实提出问题时,请考虑提供建议的措辞来纠正问题。由于并不缺乏明确的实际意图,而且可能大多数实现都在做正确的事情,所以我希望这个问题的优先级相当低,如果没有建议的措辞,它不太可能受到太多关注。当然,解决这个问题不会改变预期的行为,例如,将 "widen" char
s 转换为 UTF8 序列:这实际上是对流库的重新设计,它可能是有序的但赢得' 作为缺陷解决的一部分完成。