Почему нельзя создать объект, содержащий член ostringstream?

У меня есть следующий пример класса, упрощенный из более крупного проекта. Он основан на каркасе ведения журнала, который использует область ведения журнала для завершения записи журнала в деструкторе.

Код ниже не будет компилироваться, потому что конструктор является неявно удаленной функцией (редактировать: не верно), которая, кажется, как-то связана с std::ostringstream объект. Я смущен этим, потому что я думаю, что я должен быть в состоянии непосредственно построить std::ostringstream, что означало бы, что я должен иметь возможность непосредственно построить Container объект.

#include <iostream>
#include <sstream>

class Container {
public:
std::ostringstream  bufferStream;

public:
Container();    // constructor
~Container();
};

Container::Container() {
bufferStream << "Hello ";
}

Container::~Container() {
std::cout << bufferStream.str() << " [end]" << std::endl;
}

// === Main method ===

int main() {

Container().bufferStream << "world";   // works fine

{                                      // causes tons of compiler errors
Container cont = Container();
cont.bufferStream << "world!";
}

return 0;
}

Обратите внимание, что строка с надписью «отлично работает» делает именно это. Кажется, для создания экземпляра анонимного Container объект, который содержит новый std::ostringstream, который может быть напрямую доступен для вывода «мира». Container сам создает часть сообщения «Hello», а его деструктор очищает буфер.

Почему не вторая часть, в которой Container объект назван и сохранен, работает правильно? Вот пример ошибок, которые я получаю:

error.cpp: In function ‘int main()’:
error.cpp:28:36: error: use of deleted function ‘Container::Container(const Container&)’
Container cont = Container();
^
error.cpp:4:7: note: ‘Container::Container(const Container&)’ is implicitly deleted because the default definition would be ill-formed:
class Container {
^
error.cpp:4:7: error: use of deleted function ‘std::basic_ostringstream<char>::basic_ostringstream(const std::basic_ostringstream<char>&)’
In file included from error.cpp:2:0:
/usr/include/c++/4.8/sstream:387:11: note: ‘std::basic_ostringstream<char>::basic_ostringstream(const std::basic_ostringstream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
class basic_ostringstream : public basic_ostream<_CharT, _Traits>

… и так далее.

3

Решение

Это будет работать нормально:

Container cont;
cont.bufferStream << "world!";

Но это:

Container cont = Container();

включает в себя конструктор копирования. std::ostringstream не копируемо, что делает Container не копируемый, поэтому сообщение об ошибке говорит о том, как Container::Container(const Container&) неявно удаляется из-за std::basic_ostringstream<char>::basic_ostringstream(const std::basic_ostringstream<char>&) неявно удаляется.

Обратите внимание, что даже если эта копия будет удалена, требование исключения из копирования / перемещения заключается в том, что копирование / перемещение должно начинаться с начала.

9

Другие решения

Как объяснил Барри, ostringstream не копируемый Поскольку конструктор копирования по умолчанию копирует конструирует член за членом, он не может быть сгенерирован здесь.

Однако, если вы будете следовать правило трех вы бы создали конструктор копирования (а также оператор назначения копирования), делать то, что нужно для струнного потока. Тогда это будет работать:

class Container {
...
Container(const Container&); //Copy constructor
};

Container::Container(const Container &c) {
bufferStream << c.bufferStream.rdbuf();
}

Онлайн демо

3

По вопросам рекламы [email protected]