如何确定输出流链是否结束?

how to find out if output stream chain is ended?(如何确定输出流链是否结束?)

本文介绍了如何确定输出流链是否结束?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要达到什么目的?

如何确定流链是否结束?看看下面的函数(所有这些函数都在这个问题的 LogRouter 类中):

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);

我希望能够使用

router.log(LogLevel::Alert) << "test stream " << 15;

我尝试过的:

  • std::ostream 运算符重载不接受压缩变量.

  • 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;
}

这给了我我想要的语法明智,但我需要在每个结束时调用额外的 LogRouter::end():

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();

我也有 std::endl 的语法,但如果我能在最后不加任何内容的情况下调用它,那将是最好的.

I have a syntax for std::endl also but it would be best if I can call it without anything in the end.

问题

有没有办法知道流链的末端.类似于使用递归可变参数模板函数时可以执行的操作.

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() << ")
";
    }
};

logstream trace() {
    return logstream("trace");
}

int main()
{
    trace() << "hello, world";
}

使用的流缓冲区(在本例中为std::stringbuf,但也可以是自定义流缓冲区)被创建为基类,以便在 std::ostream 之前构造它.原则上它是一个数据成员,但数据成员是在基类之后构造的.因此,它变成了一个 private 基类.

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.

事实证明 std::ostream 有一个 virtual 基类 (std::ios),这会导致 std::ostream 仍然在 std::stringbuf 之前构造,如果用于 std::stringbuf 的正常继承.使用 virtual 继承并使 std::stringbuf 成为第一个基类,确保它确实首先被构造.

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.

这篇关于如何确定输出流链是否结束?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:如何确定输出流链是否结束?

基础教程推荐