c++ - 如何在 C++ 中编写 ofstream vector ,它接收所有不同的输出流,如 cout、字符串流和 ofstream

标签 c++ c++11 vector ostream

我正在尝试实现一个记录器,它可以注册到多个流,如 ostringstream、ofstream 等。我试图实现这样的功能

void register_stream(std::ostream& a);

载体如下

std::vector<std::ostream> streams;

寄存器流和运算符重载如下

void logger::register_stream(std::ostream &a)`

{

    streams.push_back(a);

}

template <typename T>

void logger::operator<<(T const& value)

{

    for (auto stream : streams)

    {

        (stream) << value;

    }

}

我正在尝试实现一个记录器,以在单个运算符“<<”调用上写入所有已注册的流。

调用代码如下:

std::ostringstream os;
    std::ofstream f;
    logger l;
    l.register_stream(f);
    l.register_stream(os);
    l << "log this";

我收到一个错误:

C2280: std::basic_ostream<char,std::char_traits<char>>::basic_ostream(const std::basic_ostream<char,std::char_traits<char>> &): attempting to reference a deleted function

如有任何帮助,我们将不胜感激。

最佳答案

ostream格式化和写入底层 streambuf .这样当你使用 operator<<多次不必要地多次格式化相同的输入。更优化的方法是格式化一次,然后将格式化后的输出复制到多个底层 stream s 使用无格式输出函数 ostream::write .

方便有std::ostream接口(interface),以便您可以将其传递给期望 std::ostream 的现有函数界面。

您基本上需要一个自定义 streambuf执行。从头开始编写一个是很好的学习经验,但乏味且容易出错,因为 streambuf interface有点难以理解和正确实现。使用 The Boost Iostreams Library相反。

工作示例:

#include <boost/iostreams/stream.hpp>
#include <algorithm>
#include <iostream>
#include <vector>

struct MultiSink {
    using char_type = char;

    struct category
        : boost::iostreams::sink_tag
        , boost::iostreams::flushable_tag
    {};

    std::vector<std::ostream*> sinks_;

    std::streamsize write(char const* s, std::streamsize n) {
        for(auto sink : sinks_)
            sink->write(s, n);
        return n;
    }

    bool flush() {
        for(auto sink : sinks_)
            sink->flush();
        return true;
    }

    void add_sink(std::ostream& s) {
        sinks_.push_back(&s);
    }

    void remove_sink(std::ostream& s) {
        sinks_.erase(std::remove(sinks_.begin(), sinks_.end(), &s), sinks_.end());
    }
};

int main() {
    MultiSink sink;
    boost::iostreams::stream<MultiSink> stream(sink);
    stream->add_sink(std::cout);
    stream->add_sink(std::cerr);

    stream << "Hello, world!" << std::endl;
}

请注意,代码假定已注册流的生命周期超过多接收器。如果不是这种情况,您需要在销毁之前从多接收器注销流。

关于c++ - 如何在 C++ 中编写 ofstream vector ,它接收所有不同的输出流,如 cout、字符串流和 ofstream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52277862/

相关文章:

c++ - 在字符串 vector 中创建 20,000 个 MAC 地址

c++ - 使用 boost asio 进行多线程 http 处理是否需要线程?

c++ - 前向声明模板函数的必要性

c++ - 用另一个和额外元素的内容初始化 C++ (11) std::vector

c++ - 检测对临时的悬空引用

C++ 枚举和内联 header 函数

c++ - 为什么调用 `int* Get()` 而不是 `const int& Get()` ?

3d - 方向向量的欧拉旋转

c++ - 从 vector 中删除对象

c++ - 如何用满足某些条件的另一个 vector 中的数据填充 std::vector