我正在尝试开发一个Exception类,该类允许收集相关的数据流样式。
在Custom stream to method in C++?之后,我扩展了自己的类(class):
class NetworkException : public std::exception, public std::ostream
从流中选择错误数据,然后返回通过
.what()
获取的任何错误数据。然后我尝试了这样的事情:
try {
ssize_t ret = send(sock, headBuffer, headLength, MSG_MORE);
if (ret <= 0) throw NetworkException() << "Error sending the header: " << strerror(errno);
// much more communication code
} catch (NetworkException& e) {
connectionOK = false;
logger.Warn("Communication failed: %s",e.what());
}
但是编译器会产生一个错误:
HTTPClient.cpp:246:113: error: use of deleted function 'std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)'
(这就是
throw
的行。)我意识到流没有复制构造函数,但是我认为捕获一个引用而不是对象就足够了。我该如何克服-我可以扔一个“吞下”流的物体吗?
最佳答案
您不能使用默认的复制构造函数复制包含流对象的对象,但是可以编写自己的复制构造函数来复制流的内容。
#include <iostream>
#include <sstream>
struct StreamableError : public std::exception {
template <typename T>
StreamableError& operator << (T rhs) {
innerStream << rhs;
return *this;
}
StreamableError() = default;
StreamableError(StreamableError& rhs) {
innerStream << rhs.innerStream.str();
}
virtual const char* what() const noexcept {
str = innerStream.str(); //this can throw
return str.c_str();
}
private:
std::stringstream innerStream;
mutable std::string str;
};
int main() {
try {
throw StreamableError() << "Formatted " << 1 << " exception.";
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
}
}
上面的解决方案并不完美。如果
str = innerStream.str()
抛出,那么std::terminate
将被调用。如果要使what
方法完全成为noexcept
,则有两种选择:str
变量中。这样一来,您将无法在调用前调用what
方法获取异常消息。 str
运算符内部的<<
变量中。在这种情况下,您将能够在抛出之前获取异常消息,但是每次调用运算符(operator)时您都将复制消息,这可能是一个过大的杀伤力。 关于c++ - 我可以丢流吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37191227/