为什么标准同时具有seekpos()和seekoff()?

时间:2015-03-18 20:54:51

标签: c++ language-lawyer

标题几乎说明了一切。

我正在实施自己的streambuf课程,我想知道委员会在决定同时包括std::streambuf::seekpos()std::streambuf::seekoff()时的想法(以及相关的pubseekpos()和{ {1}})。

在我看来,pubseekoff()在我能想象的每种情况下都应该与seekpos(x)具有相同的效果。但也许我的想象力不够好。那么,为什么在seekoff(x, std::ios::beg)完全归入seekpos时你想要同时拥有两者?或者至少,为什么不让前者的默认实现只调用后者?

如果答案是"因为那就是STL所做的"或类似的,然后假设我询问STL或类似的理由。

(我意识到seekoff的第一个参数是seekposstreampos的第一个参数是seekoff。但请注意27.4.3.2 [lib。 fpos.operations]要求流位置可以转换为流偏移并返回,所以我认为这不是答案。)

2 个答案:

答案 0 :(得分:13)

这两个函数使用不同的参数:

你是完全正确的:他们可以双向转换。但是有一个微妙的语义差异:

  • streampos直观地与固定位置相关,而streamoff在某种程度上与文件中的运动相关。
  • 从另一个streampos中扣除一个streampos会产生streamoff
  • streampos添加streamoff会新增streampos
  • 其他组合是有效的,这要归功于简单的转换,但需要更多的关注。
  • 宽流使用wstreampos作为位置(因为wchar_t中的位置显然与char流中的位置具有不同的含义。
  • 但是宽流使用streamoff进行动作,因为它是与位置相比的相对运动。

如果您使用模板编程,这些语义差异对于特征S::pos_typeS::off_type更明确。

真正的起源

无论这些语义潜意识如何,这种差异的真正起源都是历史性的,与 C标准库有关,正如Plauger先生在this article中所解释的那样:

  • streamoff的设计考虑了C标准库的fseek()ftell(),使用long进行定位。
  • streampos适用于使用fsetpos()参数的fgetpos()fpos_t

我可以验证这是C89标准中的情况。由于原始K& R中没有提到这些功能,因此UNIX历史学家可能会更多地了解更远的路径。

This paper解释了标准委员会最近的想法。似乎历史性的差异受到了质疑,现在还不再清楚是否真的需要它。

答案 1 :(得分:2)

  

我想知道委员会在决定同时包括std :: streambuf :: seekpos()和std :: streambuf :: seekoff()时的想法(同样对于相关的pubseekpos()和pubseekoff())

streampos表示从流开始的绝对位置。因此,seekpos()寻求特定的位置。

streamoff表示距离给定位置的偏移量。因此,seekoff()可以相对于任何给定的位置寻求。这就是为什么它有dir参数来指定如何解释偏移量 - 从流的开头/结尾开始的偏移量,或相对于流的当前位置的偏移量。

不同的语义,所提供的功能不同。

  

在我看来,在我能想象的每种情况下,seekpos(x)应该与seekoff(x,std :: ios :: beg)具有相同的效果。

这在逻辑上是什么,是的。虽然可以优化实际实现,例如通过考虑当前位置来最小化所涉及的物理搜索量,尤其是对于文件流。要让操作系统一直回到文件的开头再向前移动并不总是有效的。

  

那么,为什么当搜索引擎完全被搜索包含时,你想要两者兼顾?

因为有时直接寻找特定位置是有意义的,有时寻求相对偏移是有意义的。这取决于具体情况。这两种情况都有其用途。

  

那么,为什么当搜索引擎完全被搜索包含时,你想要两者兼得?

便利。取决于调用代码的设计,无论是跟踪绝对位置还是相对偏移。

  

或者至少,为什么不让前者的默认实现只调用后者?

可能是。它是实现定义的。

  

但请注意,27.4.3.2 [lib.fpos.operations]要求流位置可以转换为流偏移并返回,所以我认为这不是答案。)

Convertible 是这里的关键词。仅仅因为它们可以转换彼此并不意味着它们在语义上相等彼此。