vendredi 9 octobre 2020

Does standard mandates that stream-constructors don't access stream buffer?

This (pretty old) article on iostreams and streambuf argues, that the following code is OK:

class DerivedStreamBuf : public std::streambuf {
  // ...
};

class DerivedOutputStream : public std::ostream {
  public:
    DerivedOutputStream():
      std::ios(0), std::ostream(&dsb) {}        //1
    // ...
  private:
    DerivedStreamBuf dsb;
    // ...
};

It might be problematic, because when ostream is constructed dsb isn't yet initialized and thus UB could be the effect. For the destructor it might be the other way around: dsb is already destructed and could be used in the destructor of ostream.

However, the article argues, "the C++ standard mandates that no parent class constructors or destructors (ios, istream, or ostream) access the stream buffer".

While the case of destructor is straight forward, e.g. for ~ostream:

virtual ~basic_ostream(); Remarks: Does not perform any operations on rdbuf().

It is less clear for constructor:

explicit basic_ostream(basic_streambuf<charT, traits>* sb); Effects: Initializes the base class subobject with basic_­ios<charT, traits>​::​init(sb) ([basic.ios.cons]).

Does it means this is the only possible effect, does this standard-formulation not allow for other effects, which are implementation details of ´std::ostream´ and could potentially access non-initialized dsb?

My question: Does that standard guarantees, that the above code is portable, i.e. works for all standard-compliant implementations of std::ostream?

Aucun commentaire:

Enregistrer un commentaire