简体   繁体   中英

Extending C++ ostream

I'm trying to learn more about the workings of the C++ I/O stream library by extending std::streambuf . As a learning experiment, my goal is to simply create a custom stream which directs all output to std::cerr . It seems simple enough:

#include <iostream>
using namespace std;

class my_ostreambuf : public std::streambuf
{
    public:

    protected:

    std::streamsize xsputn(const char * s, std::streamsize n)
    {
        std::cerr << "Redirecting to cerr: " << s << std::endl;
        return n;
    }

};

int main()
{
    my_ostreambuf buf;
    std::ostream os(&buf);
    os << "TEST";
}

This seems to work, since it prints Redirecting to cerr: TEST . The problem is that it doesn't work when a single character (as opposed to a string) is inserted into the stream via std::ostream::sputc . For example:

int main()
{
    my_ostreambuf buf;
    std::ostream os(&buf);
    os << "ABC"; // works
    std::string s("TEST");
    std::copy(s.begin(), s.end(), std::ostreambuf_iterator<char>(os)); // DOESN'T WORK
}

The problem I guess is that xsputn doesn't handle single character insertion. (I guess sputc doesn't call xsputn internally?) But, looking over the list of virtual protected functions in std::streambuf , I don't see any function I'm supposed to override that handles single character insertion.

So, how can I accomplish this?

Single-character output is handled by overflow . Here's how you might implement overflow in terms of xsputn if xsputn does the actual outputting:

int_type overflow(int_type c = traits_type::eof())
{
    if (c == traits_type::eof())
        return traits_type::eof();
    else
    {
        char_type ch = traits_type::to_char_type(c);
        return xsputn(&ch, 1) == 1 ? c : traits_type::eof();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM