【问题标题】:C++ When are characters widened in output stream operator<<()?C++输出流运算符<<()中的字符何时加宽?
【发布时间】:2017-06-05 20:41:36
【问题描述】:

在我看来,C++ 标准存在不一致之处,特别是在 C++17 草案 (N4659) 的第 30.7.5.2.4 节中,关于何时在输出流的格式化输出操作中加宽字符( operator&lt;&lt;())。完全相同的不一致似乎反映在en.cppreference.com 中。

首先,假设以下声明:

std::ostream out;
std::wostream wout;
char ch;
wchar_t wch;
const char* str;
const wchar_t* wstr;

然后声明

  1. out &lt;&lt; ch 执行字符加宽,
  2. out &lt;&lt; str 执行字符加宽,
  3. wout &lt;&lt; ch 执行字符加宽,
  4. wout &lt;&lt; str 执行字符加宽,
  5. wout &lt;&lt; wch 执行字符加宽,
  6. wout &lt;&lt; wstr 执行字符加宽。

第一个也是最明显的不一致是 (6) 不可能为真,因为没有 widen() 函数采用 wchar_t 参数,只有一个采用 char 参数。

第二个(表面上的)不一致在 (1) 和 (2) 之间。 out &lt;&lt; "x" 应该扩大 'x',而 out &lt;&lt; 'x' 不应该扩大,这对我来说似乎很奇怪。

我误解了标准文本,还是那里有什么问题?如果后者是真的,你知道预期的行为是什么吗?

编辑:显然,这种不一致(如果我是对的)至少从 C++03(第 27.6.2.5.4 节)开始就存在于标准中。文本通过中间标准略有变化,但我在上面解释过的不一致仍然存在。

【问题讨论】:

  • 这应该是 LWG 问题。
  • "... 如果 c 的类型为 char 并且流的字符类型不是 char ,则 seq 由 out.widen(c) 组成;否则 seq 由 c 组成......" 抱歉,我的英语(一般理解,为什么不)不太好;你能指出你发现不一致的句子之一吗?
  • @Loreto 在标准的任何一个句子中都没有真正的不一致。正如我上面所描述的,(1)和(2)似乎相互冲突,Dietmar 确认(1)是正确的,而(2)是错误的(由于措辞不当而导致错误)。

标签: c++ stl language-lawyer ostream


【解决方案1】:

标准似乎并不完全正确。大多数问题源于各自操作的批量规范。不是单独处理每个重载,而是将类似的重载放在一起描述,从而导致误导性规范。

但我怀疑,任何实施者都无法理解其意图。本质上,当char 插入到非char 流中时,字符需要widen()ed 才能获得流的字符类型的字符。这种扩展旨在将源字符集中的一个字符映射到流的宽字符集中的一个字符。

请注意,IOStreams 规范假定流中字符的原始概念是单个实体。由于创建了规范(针对 C++1998 版本),文本并没有真正更新,但是随着 Unicode 的广泛使用,流中的“字符”实际上是编码的字节。尽管流在这个修改后的环境中大部分都可以正常工作,但并没有真正正确地支持一些有助于处理 Unicode 字符的灵活性。缺少将一个字符“扩展”为 UTF8 字节序列的东西可能就是其中之一。

如果您认为流部分中的不一致/不正确之处需要解决,请提交缺陷报告。提交缺陷报告的说明在http://isocpp.org。当您确实提出问题时,请考虑提供建议的措辞来纠正问题。由于并不缺乏明确的实际意图,并且可能大多数实现无论如何都会做正确的事情,我希望这个问题得到相当低的优先级,并且如果没有提议的措辞,它不太可能受到太多关注。当然,解决这个问题不会改变预期的行为,例如,将chars“扩大”为 UTF8 序列:这实际上是对流库的重新设计,可能是有序的,但不会完成作为缺陷解决的一部分。

【讨论】:

  • 在很多情况下,标准都指定了无条件的 widen 调用,但没有任何迹象表明对于相同字符类型的情况可能会跳过它。
  • @T.C.:当然。如果你觉得它应该被修复,提出一个缺陷。如果规范最终要求在所有情况下都调用widen(),那么它会产生一个简洁的效果,希望所有实现者都应该意识到widen() 的结果需要被缓存,所以virtual 函数只被调用一次。
  • 确实——我认为可以肯定地说,委员会可能会看好至少彻底改革 iostreams 的想法——但条件是这样做是非常重要的任务,因此任何此类提案都将受到大量审查,并且需要解决许多不成文、鲜为人知且最有可能相互冲突的目标才能获得成功。
  • 考虑到 char 类型已经意味着 UTF-8 代码单元,您如何想象将 char“扩展”为 UTF-8 字符序列? (Unicode 之前的语言环境除外,但我们正在谈论未来..)
  • @DietmarKühl 如果加宽 char -> wchar_t 将基本源字符集中的字符从源字符编码映射到特定于语言环境的宽字符编码,这不是“加宽”@ 987654332@ -> char 需要将这些相同的字符从源字符编码映射到特定于语言环境的非宽(多字节)字符编码?或者,对于基本源字符集中的所有字符,源和区域设置特定的非宽字符编码是否假定相同?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多