I have the following piece of code that surprised me (using libstdc++4.8)...
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main() {
std::string s("some content");
std::stringstream ss(s, std::ios::in|std::ios::ate);
std::istream& file = ss;
//ss.clear(); Makes no difference...
std::cout << "tellg() pos: " << file.tellg() << std::endl;
return 0;
}
... which has the following output.
tellg() pos: 0
This behaviour is different to when using std::ifstream(std::ios::ate).
This is fully in-line with what standard tells us. Here are relevant details:
The version of constructor you've used:
Constructs a std::basic_stringbuf object by calling the default constructor of std::basic_streambuf, initializes the character sequence with an empty string, and sets the mode to which, than followed by initializing the associated character sequence as if by calling str(new_str).
Default constructor of basic_stringbuf
is not interesting here, and than std::basic_stringbuf::str
:
Deletes the entire underlying character sequence of this std::basic_stringbuf and then configures a new underlying character sequence containing a copy of the contents of s. ... For append streams (mode & ios_base::ate == true), pptr() == pbase() + s.size(), so that subsequent output will be appended to the last character copied from s
And finally, tellg()
, which calls pubseekoff
on the buffer:
If which includes ios_base::in and this buffer is open for reading (that is, if ((which & ios_base::in) == ios_base::in), then repositions the read pointer std::basic_streambuf::gptr: .. then newoff is the current position of the pointer (gptr()-eback() in this case)
To sum it up: since you didn't modify get position in any way (constructor only modifies put position), it returns 0.
tellg()
returns gptr()-eback()
and providing the ios_base::in
flag in the stringstream
(and therefore the basic_stringbuf
) constructor has the postcondition gptr() == eback()
.
Thus, 0
is expected / enforced.
tellg()
returns rdbuf()->pubseekoff(0, std::ios_base::cur, std::ios_base::in)
rdbuf()
returns const_cast<basic_stringbuf*>(&sb)
.pubseekoff(0, std::ios_base::cur, std::ios_base::in)
calls seekoff(0, std::ios_base::cur, std::ios_base::in)
seekoff
returns gptr()-eback()
eback()
returns a pointer to the beginning of the get areagptr()
returns the current get pointstringstream
Initialization:
basic_stringstream (basic_string const &str, ios_base::openmode which);
Effects: Constructs an object of class basic_stringstream, initializing the base class with
basic_iostream(&sb)
and initializing sb withbasic_stringbuf(str, which)
.
basic_stringbuf(basic_string const &str, ios_base::openmode which)
Effects: Constructs an object of class basic_stringbuf, initializing the base class with
basic_streambuf()
, and initializing mode with which. Then callsstr(s)
.
void basic_stringbuf::str(const basic_string<charT,traits,Allocator>& s);
Effects: Copies the content of s into the basic_stringbuf underlying character sequence and initializes the input and output sequences according to mode.
Postconditions:
If
mode & ios_base::out
istrue
,pbase()
points to the first underlying character andepptr() >= pbase() + s.size()
holds;if
mode & ios_base::ate
istrue
,pptr() == pbase() + s.size()
holds, otherwisepptr() == pbase()
istrue
.If
mode & ios_base::in
istrue
,eback()
points to the first underlying character, and bothgptr() == eback()
andegptr() == eback() + s.size()
hold.
Where the last bit is relevant: providing ios_base::in
has the postcondition gptr() == eback()
and since tellg()
returns gptr()-eback()
the result is required to be zero.
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