【问题标题】:Why do streams still convert to pointers in C++11?为什么流仍然转换为 C++11 中的指针?
【发布时间】:2013-01-17 11:20:15
【问题描述】:

从文本文件中读取行的规范方法是:

std::fstream fs("/tmp/myfile.txt");
std::string line;
while (std::getline(line, fs)) {
   doThingsWith(line);
}

(不,it is not while (!fs.eof()) { getline(line, fs); doThingsWith(line); }!)

这是因为 std::getline 通过引用返回流参数,并且因为:

  • 在 C++03 中,流通过operator void*() const 中的operator void*() const 转换为void*,当设置fail 错误标志时计算为空指针值;
    • [C++03: 27.4.4] & [C++03: 27.4.4.3/1]
  • 在 C++11 中,流转换为 bool,通过 std::basic_ios 中的 explicit operator bool() const,当设置了 fail 错误标志时计算为 false
    • [C++11: 27.5.5.1] & [C++11: 27.5.5.4/1]

在 C++03 中,这种机制意味着以下是可能的:

std::cout << std::cout;

它正确地导致一些任意指针值被输出到标准输出流。

但是,尽管 operator void*() const 在 C++11 中已被删除,但它也可以在 C++11 模式下的 GCC 4.7.0 中为我编译和运行。

这在 C++11 中怎么可能?还有其他一些我不知道的机制在起作用吗?或者它只是一个实现“奇怪”?

【问题讨论】:

  • @Nocturno,这不是为什么的问题,因为为什么bool 而不是void *(或同等学历)。这是一个问题,据 OP 所知,为什么 C++11 说代码不应该输出地址,但确实如此。如果我误解了,请纠正我。
  • @Nocturno:我认为你误解了这个问题。这不是合理化的要求。我希望有人告诉我,尽管删除了 operator void*() const,哪些 C++11 语言功能使 std::cout &lt;&lt; std::cout 保持有效。
  • 另外,“很少有人(如果有的话)知道原因”从不成为提出“坏问题”的理由。这只是意味着只有一两个答案,而不是......哦,等一下!如果有的话,它会通过传播这些知识来提出一个的问题。
  • +1 非常好的问题+答案。这是一个非常好的线程。
  • @DougT。 “不喜欢 STL 的 iostreams 部分的另一个原因” - 由于 iostreams 不是 STL 的一部分,因此没有太多喜欢或不喜欢的地方。 (很抱歉吹毛求疵,但我希望它本着 OP 的精神);)

标签: c++ c++11 g++ std iostream


【解决方案1】:

我有理由确定这在符合 C++11 的实现中是不允许/不可能发生的。

当然,问题在于,目前大多数实现都在努力实现一致性,但还没有完全实现。可以猜测,对于许多供应商来说,这个特定的更新是一个相当低的优先级。它改进了错误检查,但在启用新技术、添加新功能、提高运行时效率等方面几乎没有(或没有)。这让编译器可以捕获您引用的错误 (some_stream &lt;&lt; some_other_stream),但实际上并没有否则会产生很大的不同。

如果我负责更新 C++11 的标准库,我认为这将是一个相当低优先级。还有其他一些更改可能同样容易(如果不是更容易)合并,并且可能对大多数程序员产生更大的影响。

使用您提供的示例之一,如果我负责更新 VC++ 标准库以利用 11 月 CTP 中添加的编译器功能,我的首要任务可能是向标准容器类型添加构造函数接受initialization_lists。这些很容易添加(我猜一个人可能会在一周内添加和测试它们)并且对程序员可以做的事情产生相当明显的明显差异。

【讨论】:

  • 虽然您的推理完全无法理解,但删除此operator void*(或将其转换为explicit operator bool)只是无操作,并且联赛比例如更快更容易。实现正确的initializer_list 构造函数。仍然是最可能的解释 +1。
  • +1 : libc++ 给出:错误:二进制表达式的操作数无效。
【解决方案2】:

直到 GCC 4.6.2,the libstdc++ code for basic_ios 显然仍然是 C++03 风格的。

我只是把它归结为“他们还没有解决这个问题”。

相比之下,the libc++ (LLVM's stdlib implementation) trunk 已经使用了operator bool()

【讨论】:

  • 它也可能是为了向后兼容而包含的“特定于实现的非便携式扩展”。
  • 对此也投反对票!这是怎么回事?这个答案有什么问题,请告诉?我知道它回答了这个问题,因为我写了这个问题。
  • 可能只是人们反对自我回答,即使他们完全可以接受。哦,好吧!
  • @PeteBecker,发现(您可以在链接中自己看到)未指定的布尔类型在一个巨大的评论中。 operator bool() 较晚。
  • 好吧,我会试着解决它。 ;) 它不会适用于 4.8,因为它即将分支。我怀疑 2011 年之前的旧标题中有很多缺失的位。我们都下定决心要添加新的大东西。
【解决方案3】:

这是一个隐藏在预先存在的标题中的错过的迷你功能。 2011年之前的组件可能存在大量遗漏和委托错误。

真的,如果有人在 gcc 中提出类似的问题,那么前往Bugzilla 并提交错误报告将是一件好事。这可能是一个低优先级的错误,但如果你开始书面记录

我会冒险将这个想法扩展到所有其他 C++ 编译器:clangVisual Studio 等。

这将使 C++ 变得更好。

附:我输入了bug in Bugzilla

【讨论】:

    猜你喜欢
    • 2020-12-10
    • 1970-01-01
    • 2011-11-24
    • 2016-08-24
    • 2014-10-22
    • 2015-03-26
    • 2011-04-03
    • 1970-01-01
    • 2015-04-15
    相关资源
    最近更新 更多