[英]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
的最开始时仍然收到错误。
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>&)'
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.logString
是const
, a.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;
}
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. 重载决策选择一个已删除的运算符,理所当然,您将收到编译错误。
logline_t& operator =(const logline_t& a) {
logString.str(a.logString.str());;
logLevel = a.logLevel;
currentTime = a.currentTime;
return *this;
}
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(¤tTime, 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.