Home:ALL Converter>Why are move semantics for a class containing a std::stringstream causing compiler errors?

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

Ask Time:2012-08-18T12:39:48         Author:x-x

Json Formatter

How can I make this simple class movable? What I thought was correct just produces a wall of errors...

#include <iostream>
#include <sstream>
#include <utility>

class message
{
    public:
        message() = default;

        // Move constructor
        message( message &&other ) :
            stream_( std::move( other.stream_ ) ) // Nope
        {}

        // Move assignment
        message &operator=( message &&other )
        {
            if ( this != &other )
            {
                stream_ = std::move( other.stream_ ); // Nope #2
            }
            return *this;
        }

    private:
        message( const message & ) = delete;
        message &operator=( const message & ) = delete;

        std::stringstream stream_;
        // Other member variables omitted
};

int main()
{
    message m;

    return 0;
}

Compile:

$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
$ g++ -Wall -Wextra -std=c++0x move.cpp -o move

... and get a wall of errors about the copy assignments being called for various base classes of the stringstream.

move.cpp: In constructor ‘message::message(message&&)’:
move.cpp:12:40: error: use of deleted function ‘std::basic_stringstream<char>::basic_stringstream(const std::basic_stringstream<char>&)’
In file included from move.cpp:2:0:
/usr/include/c++/4.6/sstream:483:11: error: ‘std::basic_stringstream<char>::basic_stringstream(const std::basic_stringstream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
/usr/include/c++/4.6/sstream:483:11: error: use of deleted function ‘std::basic_iostream<char>::basic_iostream(const std::basic_iostream<char>&)’
In file included from /usr/include/c++/4.6/iostream:41:0,
                 from move.cpp:1:
/usr/include/c++/4.6/istream:774:11: error: ‘std::basic_iostream<char>::basic_iostream(const std::basic_iostream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
/usr/include/c++/4.6/istream:774:11: error: use of deleted function ‘std::basic_istream<char>::basic_istream(const std::basic_istream<char>&)’
/usr/include/c++/4.6/istream:57:11: error: ‘std::basic_istream<char>::basic_istream(const std::basic_istream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
/usr/include/c++/4.6/istream:57:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
[SNIP]

... This goes on for several pages.

What's wrong with my code?

Update 1: Clang 3.0 fails with similar results.
Update 2: g++ 4.7 fails also.
Update 3: Using the answers as a guide, I found this: c++11 status in libstdc++ - "27.5 Iostreams base classes: Missing move and swap operations on basic_ios." Curses!

Author:x-x,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/12015899/why-are-move-semantics-for-a-class-containing-a-stdstringstream-causing-compil
Johan Lundberg :

Update\n\nIt 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!\n\nOriginal answer\n\nIt's a missing feature in gcc (or as Xeo points out libstdc++) as of yet. \n\nhttp://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316 \n\nAccording to the standard,\n\ntypedef basic_stringstream<char> stringstream;\n\n\nand from 27.8.5, there is a public move constructor\n\nbasic_stringstream(basic_stringstream&& rhs);\n\n\nI can confirm the problem with gcc 4.7 -std=c++11, ubuntu 12.04.\n\nstd::stringstream a;\nstd::stringstream b=std::move(a);\n\n\nreading 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.)\n\nAdding a (mock) move constructor: \n\nbasic_stringstream(basic_stringstream&& rhs){}\n\n\nreduces the error to only tree lines, but \n\nuse of deleted function ‘std::basic_stringstream<char>::basic_stringstream(\n const std::basic_stringstream<char>&)’\n\n\nremains.\n\nWorkaround\n\nUse 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).",
2012-08-18T11:58:06
Xeo :

Clang 3.0 is C++98, Clang 3.1 compiles this just fine (with libc++):\n\n\n~/blargh $ cat t.cpp \n#include <sstream>\n\nint main(){\n auto get_s = []{ return std::stringstream(\"hi\"); };\n auto s = get_s();\n}\n~/blargh $ clang -v\nclang version 3.1 (trunk 152621)\nTarget: x86_64-unknown-linux-gnu\nThread model: posix\n~/blargh $ clang++ -std=c++0x -stdlib=libc++ -Wall -pedantic t.cpp \n~/blargh $\n\n\nYour example comples just fine too, so I guess it's libstdc++ that's broken in that regard.",
2012-08-18T09:35:08
yy