0

I have a set of classes that derive from basic_istream and ios_base like

  • std::stringstream,
  • boost::interprocess::basic_vectorstream,
  • boost::interprocess::bufferstream

At some point all those instances need to dump their content (emulated in the example below with a simple printf):

#include <iostream>
#include <sstream>

void dump(std::basic_istream<char> &input)
{
    const int chunk_size = 10;
    char chars[chunk_size];
    
    while (!input.eof()) {
        input.read(chars, chunk_size);
        int nread = input.gcount();
      
        printf("CHUNK: %.*s\n", nread, chars);
    }
}

int main()
{
    std::stringstream ss;
    ss << "Add some content. ";
    ss << "And then some more." << "... and that's it";
    
    foo(ss);
}

Demo

Since all is needed for the dump function is eof, read and gcount, a reference to the base class is passed to dump, so I'm assuming:

  1. All three methods are non virtual so the correct thing is called with all the needed state.
  2. There is no memory corruption implications (tried to verify by compiling the demo above with address sanitizer).

Are these assumptions correct and is there a case they'd break down?

I need to scale this logic for multiple other stream classes that are available in the codebase so the only red flag I can find is when a class redefines any of those methods, which would cause the reference to base class to break expectations.

Lorah Attkins
  • 5,331
  • 3
  • 29
  • 63
  • 2
    OT: Note that `std::istream` is an alias for `std::basic_istream`. Don't write more than needed. :) – Some programmer dude Jun 02 '23 at 08:58
  • 4
    [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) – molbdnilo Jun 02 '23 at 08:58
  • More related to your question, perhaps [a good reference](https://en.cppreference.com/w/cpp/io) might be helpful? – Some programmer dude Jun 02 '23 at 09:00
  • Why would there be a problem if any functions were virtual? Are you under the impression that there's a conversion to the base class somewhere? – molbdnilo Jun 02 '23 at 09:01
  • 1
    Lastly, using references to the base input or output stream classes (`std::istream` or `std::ostream`) is the *common*, *normal* and *standard* way to pass streams around. Then it doesn't matter if the function is called with a string stream, a file stream, `std::cin` or `std::cout`, or any other stream object. – Some programmer dude Jun 02 '23 at 09:01
  • @molbdnilo SO is amazing some times. [Here](https://coliru.stacked-crooked.com/a/f6d36c8b1a1cce8b) I'm running examples with any sanitizer I can think of and still can't figure out why sometimes I have "headers" appearing without content, or the "populate DB" function fails. It's `eof` entering the loop for empty messages ... I'll be dammed - it sent me back to inheritance articles. – Lorah Attkins Jun 02 '23 at 09:03
  • @LorahAttkins "*All three methods are non virtual so the correct thing is called with all the needed state*" - `eof()` is not virtual, as it just checks if the stream's `eofbit` flag is set. `gcount()` is not virtual either, as it just returns the byte count of the last read operation. `read()` itself is not virtual, but internally it delegates to the stream's currently assigned `streambuf`, which in turn has virtual methods. It is the `streambuf` that controls the actual I/O behavior. The different streams use different `streambuf` classes to decide where data is read from and written to. – Remy Lebeau Jun 02 '23 at 17:15

0 Answers0