【问题标题】:Is streaming a stringstream a libstdc++ extension?流式传输字符串流是 libstdc++ 扩展吗?
【发布时间】:2023-04-02 10:21:01
【问题描述】:

流式传输 stringstream 是 libstdc++ 扩展吗?该程序使用-std=c++11libstdc++gcc-4.2gcc-4.7-2 (using -std=c++03) 和clang 3.2 一起编译(感谢Andy Prowl,参见cmets)。它不能使用-std=c++11-stdlib=libc++clang 3.2 一起编译。

#include<iostream>
#include<sstream>
int main() {

  std::stringstream s; s << "b";

  std::cout << "ss: " << s << std::endl;

  return 0;
}

通过查看 ofstream 的构造函数,它可以采用 std::basic_streambuf&lt;CharT, Traits&gt;*basic_ostream&amp; st。字符串流是std::basic_istream,但两者都是std::basic_ios&lt;CharT, Traits&gt;,所以我猜它应该可以工作。

以下更改使代码在clang下编译:

  std::cout << "ss: " << s.str() << std::endl;

正确的做法是什么? cout &lt;&lt; s;cout &lt;&lt; s.str(); ?

【问题讨论】:

  • 好像可以编译here
  • 谢谢,是的!它在那里用clang编译,但我猜clang在那里使用libstdc++。
  • @AndyProwl 我已将您的信息添加到帖子中,谢谢!

标签: c++ stringstream libstdc++ libc++


【解决方案1】:

不,这是 C++03 和 C++11 之间的区别。所有流都有一个转换运算符,它可以使用if (s)while (s) 启用代码。在 C++03 中,这通常是 operator void*() 或类似的东西。

在 C++11 中,我们有显式运算符,其中 explicit operator bool() 适用于 if (s),但不适用于 cout &lt;&lt; s

【讨论】:

  • 这意味着 c++11 使用 cout &lt;&lt; ss; 破坏工作 c++03 代码? IE。以前可以工作的代码是否不再有效?
  • @gnzlbg:代码在 C++03 下编译,但对于该词的任何合理定义都工作。具体来说,它打印出来的通常是一个地址,而不是你的字符串流的内容。
  • @gnzlbg,代码在 C++03 中有效,但在 C++11 中无效。它仍然可以在 c++11 模式下使用 libstdc++,因为更改尚未实现,即gcc.gnu.org/bugzilla/show_bug.cgi?id=56193
【解决方案2】:

实际上只会在 C++98 和 C++03 中编译 ,因为所有流类都隐式转换为 void*,因为存在 operator void*() 转换函数,因此 @987654323 @ in std::cout &lt;&lt; s 会隐式转换为 void*

然而,在 C++11 中,代码将无法编译,因为 C++11 已经明确表示,它可以根据上下文转换为布尔值,而不是 void*,例如在 ifwhile 中。

【讨论】:

  • 所以这是 libstdc++ 中的一个错误?它使用 libstdc++ 与 clang 和 gcc 一起编译。
  • @gnzlbg:仅当 libstdc++ 应该符合 C++11 标准时。
  • 这里有问题。我已经验证过,你说得对,converion 运算符是explicit。但这意味着它不适用于ifwhile;显式转换运算符用于直接初始化。 (或者还有什么我错过的。)
  • @JamesKanze:它contextually 转换为布尔值,在ifwhile 中。该标准讨论了T t(e)T t = e 的区别。前者是上下文转换(松散地说),后者不是。所以bool b(s) 可以在 C++11 中正常编译,但bool b = s 不会,其中s 是一个流对象。
  • @Nawaz 是的。他们隐藏得很好。我在第 8.5 节中找不到任何提及 contextual 初始化的内容,而第 8.5 节中的措辞暗示只有在显式转换时才会发生直接转换。上下文转换规则似乎仅限于bool(根据§4),并遵守直接转换规则,尽管它们是隐式的。
【解决方案3】:

它应该与所有 C++ 编译器一起编译,但它没有做什么 你可能会期待。所有流都隐式转换为 可以在布尔表达式中使用的东西:要么 void*bool。两者都有一个&lt;&lt; 运算符 这些类型。

当您想将一个流转储到另一个流时,正确的方法是 应该是:

std::cout << s.rdbuf();

(对我来说这似乎有点奇怪,这被重载为 格式化插入运算符,因为它复制整个 streambuf 的内容,没有任何格式,甚至 忽略宽度。)

【讨论】:

  • 在这种情况下我应该更喜欢 rdbuf() 而不是 str() 吗?
  • @gnzlbg 这对我来说似乎更自然,但我认为偏好是个人的。
【解决方案4】:

流式传输 std::stringstream 没有重载,但您可以使用

std::cout << "ss: " << s.str() << std::endl;

【讨论】:

  • 如果没有重载,为什么要用libstdc++编译?是扩展吗?
  • 不,它不是扩展,转换运算符的实现方式与其他答案中指出的不同。
猜你喜欢
  • 2021-06-05
  • 1970-01-01
  • 1970-01-01
  • 2019-07-04
  • 2021-07-06
  • 2020-10-02
  • 2011-12-27
  • 2019-03-20
  • 1970-01-01
相关资源
最近更新 更多