![](/img/trans.png)
[英]`std::stringstream::operator>>()` cannot decude the template type
[英]cannot use operator= with std::stringstream
我正在尝试创建一个struct
,其中一个成员是std::stringstream
类型。 我正在使用C ++ 11,并且根据http://www.cplusplus.com/reference/sstream/stringstream/operator=/我可以做到。
这是我的代码:
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;
}
};
它没有编译,因为我收到此错误:
error: use of deleted function ‘std::basic_stringstream<char>& std::basic_stringstream<char>::operator=(const std::basic_stringstream<char>&)’
我不明白为什么它不起作用。 我试过logString = move(a.logString);
同样。 结果相同。 我将非常感谢所有的帮助。
编辑:这是我的代码,我已经应用了大多数用户建议的更改,并且在我的代码中他们没有编译。 我在struct
的最开始时仍然收到错误。
第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>&)'
第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&)'
第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&)'
如果需要任何其他信息,我将提供。
std::stringstream
不可复制。 要复制内容,您只需将一个流的内容写入另一个流:
logString << a.logString.str();
更新 :此外,如果您没有遵循使用复制构造函数实现operator=
with copy-and-swap惯用法的好建议,则必须先清除流:
logString.str({});
logString << a.logString.str();
要不就
logString.str(a.logString.str());
您也可能想要使用rdbuf()
代替:
logString << a.logString.rdbuf();
但这是不正确的,因为它改变了a.logString
的状态(尽管a.logString
是const
, a.logString.rdbuf()
是指向非const对象的指针)。 以下代码演示了这一点:
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;
流不可复制。 但它们是可移动的。
您仍然可以通过创建合适的stringstream
来使您的复制赋值运算符工作。
第三方面,将流作为成员感觉不太对劲? 如果你真的想要那个,为什么不使用ostringstream
,为什么是stringstream
? 通过对此的反思,可以改进设计(并且可能会消除当前的问题)。
使用异常安全复制/交换习惯用法创建合适的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;
}
请注意,这依赖于std::swap
,它专门用于ostringstream
。
一个更简单但原则上不例外的安全解决方法的示例:
#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=
通过移动分配其成员和基类来获取其右侧的内容。
在重载的operator=
输入参数是const
。 因此,无法移动输入参数的成员logString
。 另外,所述operator=(std::stringstream const&)
在stringstream
被声明删除。 重载决策选择一个已删除的运算符,理所当然,您将收到编译错误。
logline_t& operator =(const logline_t& a) {
logString.str(a.logString.str());;
logLevel = a.logLevel;
currentTime = a.currentTime;
return *this;
}
问题是你正在尝试复制一个不可复制的std :: stringstream对象。 你可以通过不复制对象本身但将其内容复制到新的std :: stringstream来解决这个问题 。
您还需要复制构造函数以及复制赋值运算符 。 在所谓的三规则中解释了提供这两者(以及通常也是一种析构函数)的需要。
此外,我们需要添加默认的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.