What is the expected behavior of tellg () when std :: stringstream is built using ("some content", std :: ios :: in | std :: ios :: ate)?

I have the following code snippet 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 conclusion.

tellg () pos: 0

This behavior is different than using std :: ifstream (std :: ios :: ate).

  • Is this behavior correct / expected?
  • Do I need to explicitly look for g (0, std :: ios :: end), despite opening with food?
  • clearing the state does not matter.
  • Note that the string has content .
+6
source share
2 answers

This is fully consistent with what the standard tells us. Here is the relevant information:

The constructor version that you used:

Creates an std :: basic_stringbuf object by calling the default constructor std :: basic_streambuf, initializes the character sequence with an empty string and sets the mode to which, followed by initialization of the associated character sequence, as if str (new_str) had been called.

The default basic_stringbuf is not interesting here, but << 21>:

Deletes the entire base character sequence of this std :: basic_stringbuf, and then sets up a new base character sequence containing a copy of the contents of s .... To add streams (mode and ios_base :: ate == true), pptr () == pbase () + s.size (), so that subsequent output will be added to the last character copied from s

Finally, tellg() , which calls pubseekoff in the buffer:

If ios_base :: in is enabled and this buffer is open for reading (i.e. if ((which and ios_base :: in) == ios_base :: in), then repositions read pointer std :: basic_streambuf :: gptr: .. then newoff - current pointer position (gptr () - eback () in this case)

To summarize: since you have not changed the position of the position in any way (the constructor only modifies the position of the position), it returns 0.

+2
source

In short:

tellg() returns gptr()-eback() and provides the ios_base::in flag in the stringstream constructor (and therefore basic_stringbuf ) has the postcondition gptr() == eback() .

Therefore, it is expected that 0 / is forced.

In the long:

  • 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 receive area
  • gptr() returns the current receive point

stringstream Initialization:

basic_stringstream (basic_string const &str, ios_base::openmode which);

Effects: Creates an object of class basic_stringstream, initializing the base class with basic_iostream(&sb) and initializing sb with basic_stringbuf(str, which) .

basic_stringbuf(basic_string const &str, ios_base::openmode which)

Effects: Creates an object of the basic_stringbuf class, initializes the basic class basic_streambuf() and the initialization mode with which. Then calls str(s) .

void basic_stringbuf::str(const basic_string<charT,traits,Allocator>& s);

Effects: copies the contents of s to the basic sequence of characters basic_stringbuf and initializes the input and output sequences in accordance with the mode.

Postconditions:

  • If mode & ios_base::out is true , pbase() points to the first underlying character and epptr() >= pbase() + s.size() is executed;

  • if mode & ios_base::ate is true , pptr() == pbase() + s.size() is executed, otherwise pptr() == pbase() is true .

  • If mode & ios_base::in is true , eback() points to the first base character, and both gptr() == eback() and egptr() == eback() + s.size() are saved.

If the last bit matters: providing ios_base::in has the condition post gptr() == eback() , and since tellg() returns gptr()-eback() , the result should be zero.

+2
source

All Articles