Why are move semantics for a class containing a std::stringstream causing compiler errors?

▼魔方 西西 提交于 2019-12-01 02:43:36

Update

It is required to work according to the C++11/14 standards. GCC 5.0 gets it right, and the below mentioned bug is RESOLVED. Thank you GCC team!

Original answer

It's a missing feature in gcc (or as Xeo points out libstdc++) as of yet.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316

According to the standard,

typedef basic_stringstream<char> stringstream;

and from 27.8.5, there is a public move constructor

basic_stringstream(basic_stringstream&& rhs);

I can confirm the problem with gcc 4.7 -std=c++11, ubuntu 12.04.

std::stringstream a;
std::stringstream b=std::move(a);

reading the include file include/std/sstream I find no move constructor or any mentioning of C++0x or C++11. (compare with std::string which does work.)

Adding a (mock) move constructor:

basic_stringstream(basic_stringstream&& rhs){}

reduces the error to only tree lines, but

use of deleted function ‘std::basic_stringstream<char>::basic_stringstream(
   const std::basic_stringstream<char>&)’

remains.

Workaround

Use a std::unique_ptr<std::stringstream> instead. Best is to initialize it with make_unique which comes with c++14, or take it for example from my blog cpp11style-no-new-delete (that is an earlier version, but it will work fine for this purpose).

Clang 3.0 is C++98, Clang 3.1 compiles this just fine (with libc++):

~/blargh $ cat t.cpp 
#include <sstream>

int main(){
  auto get_s = []{ return std::stringstream("hi"); };
  auto s = get_s();
}
~/blargh $ clang -v
clang version 3.1 (trunk 152621)
Target: x86_64-unknown-linux-gnu
Thread model: posix
~/blargh $ clang++ -std=c++0x -stdlib=libc++ -Wall -pedantic t.cpp 
~/blargh $

Your example comples just fine too, so I guess it's libstdc++ that's broken in that regard.

You are likely using a bad version of the library. There is no reason why your code should be invalid.

By the way, self-assignment checking assignment operators are bad.

Edit: Curiously, Visual Studio also seems to believe that basic_stringstream has no move constructor. All streams should be movable in C++11. Perhaps this is a Standard defect, or implementing the move constructor requires a C++11 feature neither yet support. Conceptually, there's no reason why it should fail, but I can't actually find anything to support that.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!