为什么包含std :: stringstream的类的移动语义会导致编译器错误? [英] Why are move semantics for a class containing a std::stringstream causing compiler errors?

查看:2633
本文介绍了为什么包含std :: stringstream的类的移动语义会导致编译器错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何使这个简单的类可移动?我认为是正确的只是产生一堵墙的错误...

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

类消息
{
public:
message()= default;

//移动构造函数
消息(消息&其他):
stream_(std :: move(other.stream_))// Nope
{ }

//移动作业
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_;
//其他成员变量省略
};

int main()
{
message m;

return 0;
}

编译:

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

...并得到一个关于正在调用的副本分配的错误对于stringstream的各种基类。

  move.cpp:在构造函数'message :: message(message& :
move.cpp:12:40:error:使用删除的函数'std :: basic_stringstream< char> :: basic_stringstream(const std :: basic_stringstream< char>&)'
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> &)'被隐式删除,因为默认定义将是错误的:
/usr/include/c++/4.6/sstream:483:11:error:使用已删除的函数'std :: basic_iostream< char> :: basic_iostream(const std :: basic_iostream< char>&)'
在/usr/include/c++/4.6/iostream:41:0包含的文件中,
从move.cpp:1:
/usr/include/c++/4.6/istream:774:11:error:'std :: basic_iostream< char> :: basic_iostream(const std :: basic_iostream< char>&)'被隐式删除,因为默认定义将是错误的:
/usr/include/c++/4.6/istream:774:11:错误:使用删除的函数'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>& )'被隐式删除,因为默认定义将是错误的:
/usr/include/c++/4.6/istream:57:11:error:使用已删除的函数'std :: basic_ios< char> :: basic_ios(const std :: basic_ios< char>&)'
[SNIP]

...



我的代码有什么问题?



1 :Clang 3.0失败,结果类似。

更新2 :g ++ 4.7也会失败。

更新3 :使用答案作为指南,我发现: c ++ 11状态in libstdc ++ - 27.5 Iostreams基类:在basic_ios上缺少移动和交换操作。诅咒!

解决方案

更新



C ++ 11/14标准。 GCC 5.0得到正确,下面提到的错误是RESOLVED。谢谢GCC团队!



原始答案



这是gcc中缺少的功能(或Xeo指出libstdc ++ )至今。



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



根据标准,

  typedef basic_stringstream< char> stringstream; 

和从27.8.5,有一个public move构造函数

  basic_stringstream(basic_stringstream&& rhs); 

我可以使用 gcc 4.7 -std = c ++ 11 ,ubuntu 12.04。

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

读取包含文件 include / std / sstream 我发现没有移动构造函数或任何提及C ++ 0x或C ++ 11。 (与 std :: string 比较。)



添加(mock)move构造函数: p>

  basic_stringstream(basic_stringstream&& rhs){} 

将错误只减少到树线,但

 使用删除的函数'std :: basic_stringstream< char> :: basic_stringstream(
const std :: basic_stringstream< char>&)'

仍然存在。



解决方法



使用 std :: unique_ptr< ; std :: stringstream> 。最好是使用c ++ 14自带的 make_unique 初始化它,或者以我的博客为例 cpp11style-no-new-delete (这是一个较早的版本,但它会正常工作) >

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!

解决方案

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).

这篇关于为什么包含std :: stringstream的类的移动语义会导致编译器错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆