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::outistrue,pbase()points to the first underlying character andepptr() >= pbase() + s.size()holds;if
mode & ios_base::ateistrue,pptr() == pbase() + s.size()holds, otherwisepptr() == pbase()istrue.If
mode & ios_base::inistrue,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