C++装饰basic_iostream类

0xb*_*00d 5 c++ fstream iostream ios

我想做类似以下代码的事情:

class foo
{
private:
    std::fstream* m_stream;

public:
    foo(std::fstream* stream) : m_stream(stream) { }

    foo& write(char const* s, std::streamsize count)
    {
        if (/*condition*/)
        {
            m_stream->write(s, count);
        }
        else
        {
            // ...
        }

        return *this;
    }

    foo& read(char* s, std::streamsize count)
    {
        if (/*condition*/)
        {
            m_stream->read(s, count);
        }
        else
        {
            // ...
        }

        return *this;
    }
};
Run Code Online (Sandbox Code Playgroud)

我需要为所有类似的方法添加相同的行为(例如put).这不应仅适用于文件流,而应适用于所有其他流类.有没有简单的方法来允许这些功能?

Sve*_*ven 5

许多格式化的输出operator(operator<<)直接写入底层流缓冲区.为了以一般方式完成此操作,您需要做的是从std :: basic_streambuf派生一个类,它将所有数据转发到另一个std :: basic_streambuf,然后可选地创建一个最小的std :: basic_ostream实现来使用您的流缓冲更容易.

我不会说这很容易,但这是以可影响所有流类型的方式执行此操作的唯一方法.

下面是一个最小流缓冲区的示例,它转发到另一个流缓冲区(并执行一些无意义的转换只是为了演示您可以做什么),以及一个附带的流:

#include <iostream>
#include <streambuf>

template<typename CharType, typename Traits = std::char_traits<CharType> >
class ForwardingStreamBuf : public std::basic_streambuf<CharType, Traits>
{
public:
    typedef Traits traits_type;
    typedef typename traits_type::int_type int_type;
    typedef typename traits_type::pos_type pos_type;
    typedef typename traits_type::off_type off_type;

    ForwardingStreamBuf(std::basic_streambuf<CharType, Traits> *baseStreamBuf)
        : _baseStreamBuf(baseStreamBuf)
    {
    }

protected:
    virtual int_type overflow(int_type c = traits_type::eof())
    {
        if( _baseStreamBuf == NULL )
            return traits_type::eof();

        if( traits_type::eq_int_type(c, traits_type::eof()) )
            return traits_type::not_eof(c);
        else
        {
            CharType ch = traits_type::to_char_type(c);
            if( ch >= 'A' && ch <= 'z' )
                ch++; // Do some meaningless transformation
            return _baseStreamBuf->sputc(ch);
        }
    }

    virtual int sync()
    {
        if( _baseStreamBuf == NULL )
            return -1;
        else
            return _baseStreamBuf->pubsync();
    }
private:
    std::basic_streambuf<CharType, Traits> *_baseStreamBuf;
};

template<typename CharType, typename Traits = std::char_traits<CharType> >
class ForwardingStream : public std::basic_ostream<CharType, Traits>
{
public:
    ForwardingStream(std::basic_ostream<CharType, Traits> &stream)
        : std::basic_ostream<CharType, Traits>(NULL), _buffer(stream.rdbuf())
    {
        this->init(&_buffer);
    }

    ForwardingStreamBuf<CharType, Traits>* rdbuf() const
    {
        return &_buffer;
    }
private:
    ForwardingStreamBuf<CharType, Traits> _buffer;
};
Run Code Online (Sandbox Code Playgroud)

这可以非常简单地使用:

int main()
{
    ForwardingStream<char> test(std::cout);
    test << "Foo" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

哪个会输出Gpp.我希望在你的路上帮助你.