What happens to the basic_ostream base when basic_iostream is moved?
c++, c++11, iostream
Solution
As you point out, the spec for:
explicit basic_iostream(basic_streambuf<charT,traits>* sb);
initializes both bases. I've never been ok with that:
http://cplusplus.github.com/LWG/lwg-closed.html#135
as it causes the single `basic_ios::init()` function to be called twice on the same virtual base object. The committee ruled that this double initialization was harmless. I disagreed strongly enough that I refused to implement the specification in regards to this detail. But the spec says to double initialize the virtual base class.
When it came time to specify the `basic_iostream` move constructor, I was in the driver's seat. And so I specified it how I thought best (to not doubly initialize `basic_ios`). That decision has yet to be challenged, but probably will be eventually.
Note that in order to avoid the double initialization, the `basic_ostream` default constructor has to be carefully crafted to do absolutely nothing. And by nothing I really mean nothing. No zero initialization:
protected:
_LIBCPP_ALWAYS_INLINE
basic_ostream() {} // extension, intentially does not initialize
Fortunately the base classes of `basic_ostream` are actually specified to do nothing in their default constructors. So everything just works: `basic_ostream` default constructs and doesn't touch memory. Then derived clients call `init(basic_streambuf<char_type, traits_type>*)` exactly once to do the actual construction of `basic_ios`/`ios_base`.
It's a really messy design. By refusing to double initialize the virtual base, I feel libc++ makes the design a little less messy, and a little more reliable. This is standard behavior for the move constructor, and not standard behavior for the constructor taking a `streambuf*`.
Problem
Just when I thought I understand the multi-pass move construction of iostreams in C++11 (thanks to https://stackoverflow.com/a/8156356/273767 for the intro), I ran into this: §27.7.2.5.1[iostream.cons]/3 `basic_iostream(basic_iostream&& rhs);` `3` Effects: Move constructs from the rvalue rhs by constructing the `basic_istream` base class with `move(rhs)`. So what happens to the other base, `basic_ostream`? I see libc++ gave `std::basic_ostream` a protected default constructor, which is called here (and also, in contradiction to the letter of §27.7.2.5.1/1, in the normal constructor of basic_iostream), and does nothing. Is that how it's supposed to be?