如何找出输出流链是否结束? [英] how to find out if output stream chain is ended?
问题描述
我想实现什么?
如何找到流链是否结束?看看下面的函数(所有这些函数都在这个问题中的一个LogRouter类中):
template< typename首先,typename。 ..休息>
void log(const LogLevel& level_,First first_,Rest ... rest_){
sstream< first_<< ;
log(level_,rest _...);
}
void log(const LogLevel& level_){
for(auto& route:routes)
route-> stream()< ; sstream.str()<< std :: endl;
sstream.clear();
sstream.str();
}
我想在上面实现完全相同的功能,但使用流。因此,当我到达一个流的结尾,它需要发送最终数据到路由,而不是使用
路由器。 log(LogLevel :: Alert,test stream,15);
我想要能够使用
router.log(LogLevel :: Alert)< 测试流< 15;
我尝试过的:
-
std :: ostream
操作符重载不接受打包变量。 -
逐个遍历每个单独传递的值。如下:
struct LogEnd {};
static LogEnd end(){return LogEnd; }
template< typename T> LogRouter& operator<<(const T& value){
sstream<<值;
return * this;
}
LogRouter& log(const LogLevel& level_){
currentLogLevel = level_; //必须添加另一个变量
return * this;
}
void operator<<(const LogEnd& end){
for(auto& route:routes)
route.stream < sstream.str()<< std :: endl;
currentLogLevel = LogLevel :: None;
}
这给了我想要的语法,但我需要调用额外
LogRouter :: end()
在每个log(LogLevel :: Alert)<< 测试流< 15 << LogRouter :: end();
我有一个语法
std :: endl
问题 / strong>
有没有办法知道流链的结束。
您可以将有趣的逻辑放入流的析构函数中。显然,我也会适当地处理流,而不是做一些看起来像流的东西,但不是一个真正的流:
#include< iostream>
#include< sstream>
#include< string>
class logstream
:private virtual std :: stringbuf
,public std :: ostream {
std :: string level;
public:
logstream(std :: string l)
:std :: ostream(this)
,level(l){
}
(logstream&&& other)
:std :: stringbuf(std :: move(other))
,std :: ostream std :: move(other.level)){
this-> rdbuf(0);
}
〜logstream(){
std :: cout< 在这里做一些有趣的事情(
<< this-> level<<,<< this-> str()<<)\\\
}
};
logstream trace(){
return logstream(trace);
}
int main()
{
trace()< 你好,世界;
}
使用的流缓冲区( std :: stringbuf
在这种情况下,但它也可以是一个自定义流缓冲区)作为一个基类,它在 std :: ostream
之前构建。原则上,它是一个数据成员,但是数据成员是在基类之后构造的。因此,它是一个 private
基类。
原来是 std :: ostream
有一个 virtual
基类( std :: ios
std :: ostream
仍然在之前构造std :: stringbuf
如果正常继承用于 std :: stringbuf
。使用 virtual
继承并使 std :: stringbuf
第一个基类确保它首先被构造。 p>
What I am trying to achieve?
How can I find if a stream chain is ended? Look at the function below (all these functions are inside a LogRouter class in this question):
template<typename First, typename... Rest>
void log(const LogLevel &level_, First first_, Rest... rest_) {
sstream << first_ << " ";
log(level_, rest_...);
}
void log(const LogLevel &level_) {
for(auto &route : routes)
route->stream() << sstream.str() << std::endl;
sstream.clear();
sstream.str("");
}
I want to achieve the exact same functionality in the above but using streams. So, when I reach an end of a stream it needs to send the final data to the routes and instead of using
router.log(LogLevel::Alert, "test stream", 15);
I want to be able to use
router.log(LogLevel::Alert) << "test stream " << 15;
What I have tried:
std::ostream
operator overloading does not accept packed variables.going through every single passed value one by one. Like below:
struct LogEnd {}; static LogEnd end() { return LogEnd; } template<typename T> LogRouter &operator<<(const T &value) { sstream << value; return *this; } LogRouter &log(const LogLevel &level_) { currentLogLevel = level_; //had to add another variable return *this; } void operator<<(const LogEnd &end) { for(auto &route : routes) route.stream() << sstream.str() << std::endl; currentLogLevel = LogLevel::None; }
This gives me what I want syntax wise but I need to call the additional
LogRouter::end()
at the end of every:router.log(LogLevel::Alert) << "test stream " << 15 << LogRouter::end();
I have a syntax for
std::endl
also but it would be best if I can call it without anything in the end.
Question
Is there a way to know an end of a stream chain. Something similar to what you can do when using recursive variadic template function.
You could put the interesting logic into the stream's destructor. Obviously, I would also properly deal with stream rather than cooking up something which somewhat looks like a stream but isn't really a stream:
#include <iostream>
#include <sstream>
#include <string>
class logstream
: private virtual std::stringbuf
, public std::ostream {
std::string level;
public:
logstream(std::string l)
: std::ostream(this)
, level(l) {
}
logstream(logstream&& other)
: std::stringbuf(std::move(other))
, std::ostream(std::move(other))
, level(std::move(other.level)) {
this->rdbuf(0);
}
~logstream() {
std::cout << "do something interesting here("
<< this->level<< ", " << this->str() << ")\n";
}
};
logstream trace() {
return logstream("trace");
}
int main()
{
trace() << "hello, world";
}
The stream buffer used (std::stringbuf
in this case but it could also be a custom stream buffer) is made a base class to have it constructed before the std::ostream
. In principle it is meant to be a data member but data members are constructed after the base classes. Thus, it is made a private
base class instead.
It turns out that std::ostream
has a virtual
base class (std::ios
) which would cause the std::ostream
to still be constructed before the std::stringbuf
if normal inheritance where used for std::stringbuf
. Using virtual
inheritance and making the std::stringbuf
the first base class makes sure it really is constructed first.
这篇关于如何找出输出流链是否结束?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!