I have the following class example, simplified from a larger project. It's based on a logging framework that uses the logger's scope to terminate a log entry in the destructor.
The code below will not compile because the constructor is an implicitly deleted function (edit: not true), which seems to have something to do with the std::ostringstream
object. I'm confused about that because I think I should be able to directly construct a std::ostringstream
, which would mean I should be able to directly construct a Container
object.
#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;
}
Note that the line labeled "works fine" does just that. It seems to instantiate an anonymous Container
object, which contains a new std::ostringstream
, which can be directly accessed to output "world". The Container
itself creates the "Hello" part of the message and its destructor flushes the buffer.
Why doesn't the second part, in which the Container
object is named and saved, run correctly? Here is a sample of the errors I get:
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>
... and so on.
This would work fine:
Container cont;
cont.bufferStream << "world!";
But this:
Container cont = Container();
involves the copy constructor. std::ostringstream
is not copy-constructible which makes Container
not copy-constructible, hence the error message talking about how Container::Container(const Container&)
is implicitly deleted due to std::basic_ostringstream<char>::basic_ostringstream(const std::basic_ostringstream<char>&)
being implicitly deleted.
Note that even though this copy would be elided, a requirement of copy/move elision is that the copy/move must be possible to begin with.
As Barry explained, the ostringstream
isn't copy constructible. As the default copy constructor copy-constructs member by member, it can't be generated here.
However, if you'd follow the rule of three you'd create a copy constructor (and also a copy assignment operator), doing what is needed for the stringstream. Then it would work:
class Container {
...
Container(const Container&); //Copy constructor
};
Container::Container(const Container &c) {
bufferStream << c.bufferStream.rdbuf();
}
来源:https://stackoverflow.com/questions/36409259/why-cant-an-object-containing-a-ostringstream-member-be-constructed