0

GIVEN:

A class MyStream derived of std::basic_istream<> contains a pointer subject to a std::basic_istream<> object. It shall respond to tellg() and read() with modified content from the corresponding responses of subject.

template <class T> MyStream :
   public std::basic_istream<typename T::char_type, typename T::traits_type> {

   std::basic::istream<...>*   subject;

   ...
};

PROBLEM: The functions tellg(), seekg() and read() as well as the status-flag functions are not virtual.

QUESTION: How can a MyStream object pass tell, seek, and read to subject, forward the response to the caller and modifiy the status flags so that they correspond to the flags of subject?

Frank-Rene Schäfer
  • 3,182
  • 27
  • 51
  • The trick is to use a different / derived [`streambuf`](https://en.cppreference.com/w/cpp/io/basic_streambuf) in your derived stream class. [SO: What exactly is streambuf? How do I use it?](https://stackoverflow.com/a/8117182/7478597) – Scheff's Cat Jun 15 '19 at 08:20

1 Answers1

1

Use something like this:

template <typename T> struct MyStream : public std::basic_istream<typename T::char_type, typename T::traits_type> {
   struct rdbuf_impl : public std::basic_streambuf<typename T::char_type, typename T::traits_type> {
       // overwrite what you need
       std::basic::istream<...>* subject;

       // for tellg passthru (an example)
       pos_type seekoff( off_type off, std::ios_base::seekdir dir,
                      std::ios_base::openmode which = ios_base::in | ios_base::out ) overwrite {
           return subject->pubseekoff(off, dir, which);
       }
   };
   MyStream(std::basic::istream<...>* subject) {
       auto v = new rdbuf_impl(subject);
       rdbuf(v); // set associated stream buffer 'v' in 'this'.
   }
};

EDIT: Let's consider tellg method. Looking at definition of class basic_istream::tellg (https://en.cppreference.com/w/cpp/io/basic_istream/tellg) - it is written, that tellg will call rdbuf()->pubseekoff(0, std::ios_base::cur, std::ios_base::in). Documentation for basic_streambuf::pubseekof (https://en.cppreference.com/w/cpp/io/basic_streambuf/pubseekoff) mentions, that it will call seekoff(off, dir, which). seekoff is virtual in basic_streambuf class and you can overwrite it.

Frank-Rene Schäfer
  • 3,182
  • 27
  • 51
Radosław Cybulski
  • 2,952
  • 10
  • 21
  • Would you, please, elaborate on your solution? How can I forward calls to `tellg()` etc to `subject`? How is the state of `subject` reflected in the status bits of a `MyStream`? – Frank-Rene Schäfer Jun 15 '19 at 09:58
  • Sorry, I undid the checkmark, because, I can still not see how the flags and `read()` function could be handled. It currently seems to be insanely complicated. Why would I need a buffer and cannot pass the data through without intermediate storage? – Frank-Rene Schäfer Jun 15 '19 at 21:52
  • You stated problem, that `tellg` and friends are not virtual and how to pass information around. I gave you a solution in form of an example solving `tellg` issue. Others are solved similarly. It is complicated due to a design of C++ library, which is like 20 years old, if not older. – Radosław Cybulski Jun 16 '19 at 08:35
  • It's a bitter pill, but I guess I have to swallow it--you're right. (There were marvelous library designs made 40 years ago, so no excuse to the I/O-library developers ... or maybe, I am missing the point of brilliance). – Frank-Rene Schäfer Jun 17 '19 at 08:50