为什么标准同时有seekpos()和seekoff()?
Why does the standard have both seekpos() and seekoff()?
标题几乎说明了一切。
我正在实现自己的 streambuf class,我想知道委员会在决定同时包含 std::streambuf::seekpos()
和 std::streambuf::seekoff()
时是怎么想的(对于相关的 pubseekpos()
和 pubseekoff()
).
在我看来,seekpos(x)
在我能想象到的任何情况下都应该具有与 seekoff(x, std::ios::beg)
相同的效果。但也许我的想象力不够好。那么,当 seekpos
完全包含在 seekoff
中时,您为什么要同时拥有两者?或者至少,为什么不让前者的默认实现简单地调用后者?
如果答案是 "because that is what the STL did" 或类似的,那么假设我问的是 STL 或类似的基本原理。
(我意识到 seekpos
的第一个参数是 streampos
而 seekoff
的第一个参数是 streamoff
。但请注意 27.4.3.2 [ lib.fpos.operations] 要求流位置可以转换为流偏移并返回,所以我认为这不是答案。)
I am wondering what the Committee was thinking when they decided to include both std::streambuf::seekpos() and std::streambuf::seekoff() (and similarly for the related pubseekpos() and pubseekoff()).
streampos
表示从流开头算起的绝对位置。因此,seekpos()
寻找特定位置。
streamoff
表示距给定位置的偏移量。因此,seekoff()
可以相对于任何给定位置进行搜索。这就是为什么它有一个 dir
参数来指定如何解释偏移量 - 与流的 beginning/end 的偏移量,或相对于流的当前位置的偏移量。
不同的语义,所以提供不同的功能。
It seems to me that seekpos(x) should have the same effect as seekoff(x, std::ios::beg) in every circumstance I can imagine.
从逻辑上讲,这就是它的作用,是的。尽管可以优化实际实现,例如通过考虑当前位置来最小化涉及的物理查找量,尤其是对于文件流。让 OS 一直回到文件开头只是为了再次向前移动并不总是有效的。
So, why would you want to have both when seekpos is completely subsumed by seekoff?
因为有时直接寻找特定位置是有意义的,而有时寻找相对偏移量是有意义的。这取决于具体情况。两种情况都有其用途。
So, why would you want to have both when seekpos is completely subsumed by seekoff?
方便。取决于调用代码的设计,它是否跟踪绝对位置或相对偏移量。
Or at least, why would you not make the default implementation of the former simply invoke the latter?
有可能。它是实现定义的。
But note that 27.4.3.2 [lib.fpos.operations] requires that stream positions be convertible to stream offsets and back, so I do not think this is the answer.)
Convertible 是这里的关键词。仅仅因为它们可以相互转换并不意味着它们在语义上等同。
两个函数使用不同的参数:
seekpos()
positions you in a stream, using an absolute streampos
位置
seekoff()
positions you in a stream, using a relative streamoff
与给定位置(开始、当前或结束)相比的偏移量
你完全正确:它们可以双向转换。但是有一个细微的语义差异:
streampos
直观地与固定位置相关,而 streamoff
与文件中的运动有某种关系。
- 从另一个
streampos
中减去一个 streampos
得到 streamoff
.
- 将
streampos
添加到 streamoff
会生成一个新的 streampos
。
- 由于易于转换,其他组合也有效,但需要更加小心。
- wide 流使用
wstreampos
作为位置(因为显然 wchar_t
中的位置与 char
流中的位置具有不同的含义)。
- 但宽流使用
streamoff
进行运动,因为它是相对于位置的相对运动。
如果您使用模板编程,这些语义差异在特征中更加明确:S::pos_type
和 S::off_type
。
真实来源
不管这些语义细节如何,这种差异的真正起源是历史性的,并且与 C 标准库 相关,正如 Plauger 先生在 this article 中所解释的那样:
streamoff
是根据 C 标准库的 fseek()
和 ftell()
设计的,它们使用 long
进行定位。
streampos
用于使用 fpos_t
参数的 fgetpos()
和 fsetpos()
。
我可以验证 C89 标准中已经存在这种情况。由于这些功能在最初的 K&R 中都没有被提及,也许 UNIX 历史学家可以告诉更多关于更遥远的路径。
This paper 解释了标准委员会最近的想法。看来历史差异受到质疑,是否真的还需要它已经不清楚了。
标题几乎说明了一切。
我正在实现自己的 streambuf class,我想知道委员会在决定同时包含 std::streambuf::seekpos()
和 std::streambuf::seekoff()
时是怎么想的(对于相关的 pubseekpos()
和 pubseekoff()
).
在我看来,seekpos(x)
在我能想象到的任何情况下都应该具有与 seekoff(x, std::ios::beg)
相同的效果。但也许我的想象力不够好。那么,当 seekpos
完全包含在 seekoff
中时,您为什么要同时拥有两者?或者至少,为什么不让前者的默认实现简单地调用后者?
如果答案是 "because that is what the STL did" 或类似的,那么假设我问的是 STL 或类似的基本原理。
(我意识到 seekpos
的第一个参数是 streampos
而 seekoff
的第一个参数是 streamoff
。但请注意 27.4.3.2 [ lib.fpos.operations] 要求流位置可以转换为流偏移并返回,所以我认为这不是答案。)
I am wondering what the Committee was thinking when they decided to include both std::streambuf::seekpos() and std::streambuf::seekoff() (and similarly for the related pubseekpos() and pubseekoff()).
streampos
表示从流开头算起的绝对位置。因此,seekpos()
寻找特定位置。
streamoff
表示距给定位置的偏移量。因此,seekoff()
可以相对于任何给定位置进行搜索。这就是为什么它有一个 dir
参数来指定如何解释偏移量 - 与流的 beginning/end 的偏移量,或相对于流的当前位置的偏移量。
不同的语义,所以提供不同的功能。
It seems to me that seekpos(x) should have the same effect as seekoff(x, std::ios::beg) in every circumstance I can imagine.
从逻辑上讲,这就是它的作用,是的。尽管可以优化实际实现,例如通过考虑当前位置来最小化涉及的物理查找量,尤其是对于文件流。让 OS 一直回到文件开头只是为了再次向前移动并不总是有效的。
So, why would you want to have both when seekpos is completely subsumed by seekoff?
因为有时直接寻找特定位置是有意义的,而有时寻找相对偏移量是有意义的。这取决于具体情况。两种情况都有其用途。
So, why would you want to have both when seekpos is completely subsumed by seekoff?
方便。取决于调用代码的设计,它是否跟踪绝对位置或相对偏移量。
Or at least, why would you not make the default implementation of the former simply invoke the latter?
有可能。它是实现定义的。
But note that 27.4.3.2 [lib.fpos.operations] requires that stream positions be convertible to stream offsets and back, so I do not think this is the answer.)
Convertible 是这里的关键词。仅仅因为它们可以相互转换并不意味着它们在语义上等同。
两个函数使用不同的参数:
seekpos()
positions you in a stream, using an absolutestreampos
位置seekoff()
positions you in a stream, using a relativestreamoff
与给定位置(开始、当前或结束)相比的偏移量
你完全正确:它们可以双向转换。但是有一个细微的语义差异:
streampos
直观地与固定位置相关,而streamoff
与文件中的运动有某种关系。- 从另一个
streampos
中减去一个streampos
得到streamoff
. - 将
streampos
添加到streamoff
会生成一个新的streampos
。 - 由于易于转换,其他组合也有效,但需要更加小心。
- wide 流使用
wstreampos
作为位置(因为显然wchar_t
中的位置与char
流中的位置具有不同的含义)。 - 但宽流使用
streamoff
进行运动,因为它是相对于位置的相对运动。
如果您使用模板编程,这些语义差异在特征中更加明确:S::pos_type
和 S::off_type
。
真实来源
不管这些语义细节如何,这种差异的真正起源是历史性的,并且与 C 标准库 相关,正如 Plauger 先生在 this article 中所解释的那样:
streamoff
是根据 C 标准库的fseek()
和ftell()
设计的,它们使用long
进行定位。streampos
用于使用fpos_t
参数的fgetpos()
和fsetpos()
。
我可以验证 C89 标准中已经存在这种情况。由于这些功能在最初的 K&R 中都没有被提及,也许 UNIX 历史学家可以告诉更多关于更遥远的路径。
This paper 解释了标准委员会最近的想法。看来历史差异受到质疑,是否真的还需要它已经不清楚了。