Как вы отмечаете, спецификация для:
explicit basic_iostream(basic_streambuf<charT,traits>* sb);
инициализирует обе базы. Я никогда не был в порядке с этим:
http://cplusplus.github.com/LWG/lwg-closed.html#135
как это приводит к одногоbasic_ios::init()
функции, которая вызывается дважды на одном объекте виртуальной базы. Комитет постановил, что эта двойная инициализация была безвредной. Я не согласился с тем, что отказался выполнять спецификацию в отношении этой детали. Но спецификация говорит о двойном инициализации виртуального базового класса.
Когда пришло время указать конструктор перемещения basic_iostream
, я был на водительском месте. И поэтому я уточнил, как я думал лучше (не дважды инициализировать basic_ios
). Это решение еще предстоит оспаривать, но, вероятно, в конечном итоге.
Обратите внимание, что во избежание двойной инициализации конструктор по умолчанию basic_ostream
должен быть тщательно обработан, чтобы ничего не делать. И ничем я ничего не имею в виду. Нет нулевой инициализации:
protected:
_LIBCPP_ALWAYS_INLINE
basic_ostream() {} // extension, intentially does not initialize
К счастью, базовые классы basic_ostream
фактически не указано ничего не делать в их конструкторы по умолчанию. Итак, все просто работает: basic_ostream
по умолчанию строит и не касается памяти. Затем производные клиенты звонят init(basic_streambuf<char_type, traits_type>*)
ровно один раз, чтобы сделать фактическую конструкцию basic_ios
/ios_base
.
Это действительно грязный дизайн. Отказавшись от двойной инициализации виртуальной базы, я чувствую, что libC++ делает дизайн немного менее грязным и немного более надежным. Это стандартное поведение для конструктора перемещения, а не стандартное поведение для конструктора, принимающего streambuf*
.
Просвещает, как всегда. – Cubbi