简体   繁体   English

不能使用operator = with std :: stringstream

[英]cannot use operator= with std::stringstream

I am trying to make a struct , in which one of the members is of std::stringstream type. 我正在尝试创建一个struct ,其中一个成员是std::stringstream类型。 I am using C++11, and according to http://www.cplusplus.com/reference/sstream/stringstream/operator=/ I can do it. 我正在使用C ++ 11,并且根据http://www.cplusplus.com/reference/sstream/stringstream/operator=/我可以做到。

Here is my code: 这是我的代码:

struct logline_t
    {
        stringstream logString; /*!< String line to be saved to a file (and printed to cout). */
        ElogLevel logLevel; /*!< The \ref ElogLevel of this line. */
        timeval currentTime; /*!< time stamp of current log line */

        logline_t& operator =(const logline_t& a)
        {
            logString = a.logString;
            logLevel = a.logLevel;
            currentTime = a.currentTime;

            return *this;
        }
    };

It doesn't compile, as I am getting this error: 它没有编译,因为我收到此错误:

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

I don't understand why it doesn't work. 我不明白为什么它不起作用。 I have tried logString = move(a.logString); 我试过logString = move(a.logString); as well. 同样。 Same result. 结果相同。 I would appreciate all help. 我将非常感谢所有的帮助。

Edit: Here is my code, I have applied the changes suggested by most of the users and in my code they do not compile. 编辑:这是我的代码,我已经应用了大多数用户建议的更改,并且在我的代码中他们没有编译。 I am still getting an error at the very beginning of the struct . 我在struct的最开始时仍然收到错误。

CLogger.h CLogger.h

Line 40: ../src/CLogger.h:40:9: error: use of deleted function 'std::basic_stringstream<char>::basic_stringstream(const std::basic_stringstream<char>&)' 第40行: ../src/CLogger.h:40:9: error: use of deleted function 'std::basic_stringstream<char>::basic_stringstream(const std::basic_stringstream<char>&)' 40: ../src/CLogger.h:40:9: error: use of deleted function 'std::basic_stringstream<char>::basic_stringstream(const std::basic_stringstream<char>&)'

CLogger.cpp CLogger.cpp

Line 86: ../src/CLogger.cpp:86:41: error: use of deleted function 'CLogger::logline_t::logline_t(const CLogger::logline_t&)' 第86行: ../src/CLogger.cpp:86:41: error: use of deleted function 'CLogger::logline_t::logline_t(const CLogger::logline_t&)' 86: ../src/CLogger.cpp:86:41: error: use of deleted function 'CLogger::logline_t::logline_t(const CLogger::logline_t&)'

Line 91: ../src/CLogger.cpp:91:9: error: use of deleted function 'CLogger::logline_t::logline_t(const CLogger::logline_t&)' 第91行: ../src/CLogger.cpp:91:9: error: use of deleted function 'CLogger::logline_t::logline_t(const CLogger::logline_t&)' 91: ../src/CLogger.cpp:91:9: error: use of deleted function 'CLogger::logline_t::logline_t(const CLogger::logline_t&)'

If any other information is needed i will provide it. 如果需要任何其他信息,我将提供。

std::stringstream is not copyable. std::stringstream不可复制。 To copy the content you can just write the content of one stream to another: 要复制内容,您只需将一个流的内容写入另一个流:

logString << a.logString.str();

Update : Also if you don't follow a good advice to implement operator= with copy-and-swap idiom using copy constructor, you have to clear the stream first: 更新 :此外,如果您没有遵循使用复制构造函数实现operator= with copy-and-swap惯用法的好建议,则必须先清除流:

logString.str({});
logString << a.logString.str();

or just 要不就

logString.str(a.logString.str());

Also you may be tempted to use rdbuf() instead: 您也可能想要使用rdbuf()代替:

logString << a.logString.rdbuf();

but this is incorrect, because it alters the state of a.logString (despite that a.logString is const , a.logString.rdbuf() is a pointer to non-const object). 但这是不正确的,因为它改变了a.logString的状态(尽管a.logStringconsta.logString.rdbuf()是指向非const对象的指针)。 This is demonstrated by the following code: 以下代码演示了这一点:

logline_t l1;
l1.logString << "hello";
logline_t l2, l3;
l2 = l1;
l1.logString << "world";
l3 = l1;
// incorrectly outputs: l2: hello, l3: world
// correct output is: l2: hello, l3: helloworld
std::cout << "l2: " << l2.logString.str() << ", l3: " << l3.logString.str() << std::endl;

Streams are not copyable. 流不可复制。 But they are movable. 但它们是可移动的。

Still you could make your copy assignment operator work by just creating a suitable stringstream . 您仍然可以通过创建合适的stringstream来使您的复制赋值运算符工作。

On the third hand it doesn't quite feel right to have a stream as a member? 第三方面,将流作为成员感觉不太对劲? And if you really want that, why not use an ostringstream , why a stringstream ? 如果你真的想要那个,为什么不使用ostringstream ,为什么是stringstream By reflecting on this, the design might be improved (and possibly that will the remove the current problem). 通过对此的反思,可以改进设计(并且可能会消除当前的问题)。


Example of workaround by creating a suitable stringstream (well, ostringstream ), using the exception safe copy/swap idiom: 使用异常安全复制/交换习惯用法创建合适的stringstream (嗯, ostringstream )的变通方法示例:

#include <sstream>
#include <utility>          // std::swap

namespace my {
    using std::ostringstream;
    using std::swap;

    struct S
    {
        ostringstream line;

        void swap_with( S& other ) noexcept
        {
            swap( line, other.line );
        }

        auto operator=( S const& other )
            -> S&
        {
            S temp( other );
            swap_with( temp );
            return *this;
        }

        S() = default;

        S( S const& other )
            : line( other.line.str() )
        {}
    };
}  // namespace my

auto main() -> int
{
    my::S o1, o2;
    o1 = o2;
}

Note that this relies on std::swap , which is specialized for ostringstream . 请注意,这依赖于std::swap ,它专门用于ostringstream


Example of a simpler but in principle not exception safe workaround: 一个更简单但原则上不例外的安全解决方法的示例:

#include <sstream>
#include <utility>          // std::swap

namespace my {
    using std::ostringstream;
    using std::swap;

    struct S
    {
        ostringstream line;

        auto operator=( S const& other )
            -> S&
        {
            line.str( other.line.str() );   // This can in theory throw, but.
            return *this;
        }

        S() = default;

        S( S const& other )
            : line( other.line.str() )
        {}
    };
}  // namespace my

auto main() -> int
{
    my::S o1, o2;
    o1 = o2;
}

Reason: 原因:

std::stringstream::operator= acquires the contents of its right hand side, by move-assigning its members and base classes. std::stringstream::operator=通过移动分配其成员和基类来获取其右侧的内容。

In your overloaded operator= the input argument is const . 在重载的operator=输入参数是const Thus, the input argument's member logString cannot be moved. 因此,无法移动输入参数的成员logString Additionally, the operator=(std::stringstream const&) in stringstream is declared deleted. 另外,所述operator=(std::stringstream const&)stringstream被声明删除。 Overload resolution chooses a deleted operator and rightfully you're getting a compile error. 重载决策选择一个已删除的运算符,理所当然,您将收到编译错误。

Solution: 解:

logline_t& operator =(const logline_t& a) {
  logString.str(a.logString.str());;
  logLevel = a.logLevel;
  currentTime = a.currentTime;
  return *this;
}

LIVE DEMO 现场演示

The problem is you are trying to copy a std::stringstream object which is non copyable . 问题是你正在尝试复制一个不可复制的std :: stringstream对象。 You can get round this by not copying the object itself but copy its contents into the new std::stringstream . 你可以通过不复制对象本身但将其内容复制到新的std :: stringstream来解决这个问题

Also you really need a copy constructor as well as the copy assignment operator . 您还需要复制构造函数以及复制赋值运算符 The need to provide both of these (and usually a destructor as well) is explained in the so-called Rule Of Three . 在所谓的三规则中解释了提供这两者(以及通常也是一种析构函数)的需要。

Also we need to add a default consructor because adding a copy constructor prevented the compiler from generating its own default constructor . 此外,我们需要添加默认的consructor,因为添加复制构造函数会阻止编译器生成自己的默认构造函数

struct logline_t
{
    std::stringstream logString; /*!< String line to be saved to a file (and printed to cout). */
    ElogLevel logLevel; /*!< The \ref ElogLevel of this line. */
    timeval currentTime; /*!< time stamp of current log line */

    // default constructor needed because we made a copy constructor
    // which deleted the compiler generated default constructor!
    logline_t()
    : logLevel(0) // set suitable defaults
    {
        gettimeofday(&currentTime, 0); // for example
    }

    // copy constructor
    logline_t(const logline_t& ll)
    : logString(ll.logString.str()) // construct from contents .str()
    , logLevel(ll.logLevel)
    , currentTime(ll.currentTime)
    {
    }

    // copy assignment operator
    logline_t& operator=(const logline_t& a)
    {
        logString.str(a.logString.str()); // assign from contents
        logLevel = a.logLevel;
        currentTime = a.currentTime;

        return *this;
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 `std :: stringstream :: operator &gt;&gt;()`无法决定模板类型 - `std::stringstream::operator>>()` cannot decude the template type operator &lt;&lt;和std :: stringstream引用? - operator<< and std::stringstream reference? C ++ std :: stringstream运算符&lt;&lt; vs(构造函数) - C++ std::stringstream operator<< vs (constructor) std :: stringstream operator >>无法将字符串转换为float - std::stringstream operator>> fails to convert string to float C ++ std :: stringstream operator <<重载 - C++ std::stringstream operator<< overloading 如何在std :: stringstream的后代中在“ this”上调用operator &lt;&lt;? - How to call operator<< on “this” in a descendant of std::stringstream? 如何在重用std :: stringstream变量时避免使用std :: stringstream.str()和std :: stringstream.clear()? - How to avoid use of std::stringstream.str() and std::stringstream.clear() while reusing std::stringstream variable? 无法转换 std::stringstream<char> 常量字符* - Cannot convert std::stringstream<char> to const char* 我可以使用std :: copy复制到stringstream中 - can I use std::copy to copy into stringstream 有什么方法可以将&lt;&lt; &lt;&lt;运算符与stringstream和带空格的字符串一起使用? - Is there any way to use << operator with stringstream and strings with spaces?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM