【问题标题】:What's the point of constexpr end istream (sentinel) iterators?constexpr end istream (sentinel) 迭代器有什么意义?
【发布时间】:2015-09-19 07:54:10
【问题描述】:

N2976 建议将constexpr 添加到标准库中的某些位置。它指出 iostreams 不适用于 constexpr 除了结束迭代器。所以istream_iteratoristreambuf_iterator 被赋予constexpr 默认构造函数,仅此而已。例如,您可以在libstdc++ implementation 中看到constexpr 在整个文件中只出现一次。引发此更改的 LWG 是 #1129。它说:

istream_iteratoristreambuf_iterator 应该支持字面量 哨兵价值观。默认构造函数经常用于 终止范围,并且很容易成为 istreambuf_iteratoristream_iterator 迭代值时 类型。 [其余省略]

这对我来说没有多大意义。谁能给我举个例子来说明他们的意思吗?

N3308 是另一篇提到但未解释该问题的论文:

一些istream_iterator<T> 构造函数必须是 constexpr 如果T 是文字类型。目的是让 现有的将T类型内联存储到的实现技术 继续工作。 [libstdc++ 这样做,_Tp _M_value] 但是,它 实际上排除了这种技术:默认和复制构造函数 的T 不需要标记constexpr,如果不是,则 istream_iterator<T> 构造函数无法实例化为 constexpr.

上面解释了琐碎的复制构造函数和析构函数,但没有解释为什么默认构造函数被标记为 constexpr。

此外,在在线 GCC 5.2.0 上进行测试时,我复制了 libstdc++ 的实现。唯一的变化是我从istream_iterator() 中删除了 constexpr。在这两种情况下,组件都是相同的。

With constexpr

Without constexpr

【问题讨论】:

  • 什么不清楚?默认构造的流迭代器通常用作结束迭代器,例如while (iter != istream_iterator())。将其作为 constexpr 可能会在循环中为我们节省一两纳秒。
  • @BoPersson 如果只有结束迭代器可以是constexpr,表达式constexpr 怎么样? (另外我不相信“为我们节省一两纳秒”可以证明一个缺陷,一篇论文,然后图书馆实施者认为它值得开发时间)
  • 我认为“移动”迭代器需要调用实时数据,因此无法在编译时确定其状态。但是 terminating 迭代器可以是完全静态的,并且可以在编译时完全推导出来,因为它所要做的就是将 equal 与耗尽数据的“移动”迭代器进行比较。
  • 表达式不是constexpr(无论如何这也不能用作循环条件),但是将iter 与一个常数进行比较可能比与其他的比较便宜。
  • @BoPersson 不是constexpr 允许在静态初始化阶段进行常量初始化吗? non-static-storage-duration 临时本地对象可以静态初始化吗?

标签: c++ c++11 constexpr istream-iterator


【解决方案1】:

这里是一个流迭代器的末端用作标记值的示例:

// istream_iterator example
#include <iostream>     // std::cin, std::cout
#include <iterator>     // std::istream_iterator

int main () {
  double value1, value2;
  std::cout << "Please, insert two values: ";

  std::istream_iterator<double> eos;              // end-of-stream iterator
  std::istream_iterator<double> iit (std::cin);   // stdin iterator

  if (iit!=eos) value1=*iit;

  ++iit;
  if (iit!=eos) value2=*iit;

  std::cout << value1 << "*" << value2 << "=" << (value1*value2) << '\n';

  return 0;
}

http://www.cplusplus.com/reference/iterator/istream_iterator/istream_iterator/

将其声明为constexpr 允许编译器将创建流尾迭代器的调用折叠成常量,而不是每次都调用一个函数。否则它可能必须在循环的每次迭代中都这样做。

【讨论】:

  • 对不起,这不是一个令人信服的论点。 Removing constexpr 将产生完全相同的程序集。
  • @user5353075 这是 1 个实现的 1 个特例。拥有它 constexpr 将保证在所有编译器和一般情况下都相同。而且,如果您的任务是检查标准库并找出可以制作 constexpr 的内容,那么省略某些内容是没有意义的,即使今天(在一个编译器上)没有真正的好处。
  • @nos 不应该 eos 具有静态或线程存储持续时间以保证在编译时执行初始化?
  • 简单示例:while ( iit != istream_iterator&lt;double&gt;() )
  • @nos 这是clang with libc++(我删除了一些 GCC 特定的东西,以及带有std:: 的限定名称)。我会在 MSVC 上测试,但 VS2013 不支持 constexpr。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-04
  • 2020-10-14
  • 2020-05-17
  • 1970-01-01
相关资源
最近更新 更多