The title pretty much says it all.
I am implementing my own streambuf class, and 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()
).
It seems to me that seekpos(x)
should have the same effect as seekoff(x, std::ios::beg)
in every circumstance I can imagine. But perhaps my imagination is not good enough. 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?
If the answer is "because that is what the STL did" or similar, then assume I am asking about the rationale for the STL or similar.
(I realize that the first argument of seekpos
is a streampos
while the first argument of seekoff
is a streamoff
. 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.)
The two functions use different parameters:
seekpos()
positions you in a stream, using an absolute streampos
positionseekoff()
positions you in a stream, using a relative streamoff
offset compared to a given position (begin, current, or end)You are perfectly right: they can be converted in both direction. But there is a subtle semantic difference:
streampos
is intuitively related to a fixed position whereas streamoff
is somehow related to motion in a file.streampos
from another streampos
makes a streamoff
.streampos
to a streamoff
makes a new streampos
.wstreampos
for the position (because obviously a position within a wchar_t
has a different meaning as a position in a char
stream).streamoff
for motion, as it is a relative movement compared to a position.If you use template programming, these semantic differences are more explicit with the traits: S::pos_type
and S::off_type
.
Regardless of these semantic subtilities, the real origin of this difference is historical, and related to the C standard library, as explained by Mr. Plauger in this article:
streamoff
was designed with fseek()
and ftell()
of the C standard library in mind, which use a long
for positioning.streampos
was meant for fgetpos()
and fsetpos()
which use an fpos_t
argument.I could verify that this was already the case in C89 standard. As neither of these functions were mentionned in the original K&R, maybe a UNIX historian could tell more about an even more distant path.
This paper explains the more recent thoughts of the standard committee. It appears that the historic difference is questioned and that it is no longer clear whether it is still really needed.
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
represents an absolute position from the beginning of the stream. Thus, seekpos()
seeks to a specific position.
streamoff
represents an offset from a given position. Thus, seekoff()
can seek relative to any given position. That is why it has a dir
parameter to specify how the offset is to be interpreted - an offset from the beginning/end of the stream, or an offset relative to the stream's current position.
Different semantics, so different functions provided.
It seems to me that seekpos(x) should have the same effect as seekoff(x, std::ios::beg) in every circumstance I can imagine.
That is logically what it does, yes. Though the actual implementation could be optimized, such as by taking the current position into account to minimize the amount of physical seeking involved, especially for file streams. It is not always efficient to make the OS go all the way back to the beginning of the file just to move forward again.
So, why would you want to have both when seekpos is completely subsumed by seekoff?
Because sometimes it makes sense to seek to a specific position directly, and sometimes it makes sense to seek to a relative offset. It depends on the circumstance. Both cases have their uses.
So, why would you want to have both when seekpos is completely subsumed by seekoff?
Convenience. Depends on the design of the calling code, whether it keeps track of absolute positions or relative offsets.
Or at least, why would you not make the default implementation of the former simply invoke the latter?
It could be. It is implementation-defined.
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 being the key word here. Just because they can be converted to each other does not mean they are semantically equal to each other.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With