Search code examples
c++streambufostringstream

Cannot set the streambuf of an ostringstream object


I want to include some std::ostringstream objects in my program for logging and error reporting purposes. Based on a setting given at compile time, the log and error streams will either collect their respective data (to be saved or whatever) or they will be redirected to std::cout and std::cerr (for debugging purposes). As far as I can tell from the references (and here) I have looked at, std::ostringstream objects inherit the rdbuf() method and I should be able to call the rdbuf() method on the stream objects, passing as an argument a pointer to the std::streambuf to associate with the streams.

However, when I try to compile I receive an error for no matching function call, with the rdbuf() method without any arguments listed as a candidate.

The error I get from g++ (4.6.3 on Ubuntu 12.04 x86_64):

sigma@SigmaSys:~/Scripts/http/test$ g++ test.cc -c -o test.o
test.cc: In constructor ‘Logger::Logger()’:
test.cc:23:43: error: no matching function for call to ‘std::basic_ostringstream::rdbuf(std::basic_streambuf*)’
test.cc:23:43: note: candidate is:
/usr/include/c++/4.6/sstream:449:7: note: std::basic_ostringstream::__stringbuf_type* std::basic_ostringstream::rdbuf() const [with _CharT = char, _Traits = std::char_traits, _Alloc = std::allocator, std::basic_ostringstream::__stringbuf_type = std::basic_stringbuf]
/usr/include/c++/4.6/sstream:449:7: note:   candidate expects 0 arguments, 1 provided

Here is a stripped down version of the source and header file:

http_utils.h

#include <string>
#include <sstream>
#include <streambuf>

#define HTTP_DEBUG_MODE 1


class Logger {
    private:
        static std::ostringstream errOut;
        static std::ostringstream logOut;

        static std::streambuf* cerrStreamBuffBackup;
        static std::streambuf* coutStreamBuffBackup;

        static std::streambuf* errOutStreamBuffBackup;
        static std::streambuf* logOutStreamBuffBackup;
    public:
        Logger();
        ~Logger();
};

http_utils.cc

#include "test.h"
#include <string>
#include <iostream>
#include <sstream>
#include <streambuf>


std::ostringstream Logger::errOut;
std::ostringstream Logger::logOut;
std::streambuf* Logger::cerrStreamBuffBackup = NULL;
std::streambuf* Logger::coutStreamBuffBackup = NULL;
std::streambuf* Logger::errOutStreamBuffBackup = NULL;
std::streambuf* Logger::logOutStreamBuffBackup = NULL;


Logger::Logger() {
    if (HTTP_DEBUG_MODE) {//Redirect logging/error to stdout/stderr
        Logger::errOutStreamBuffBackup = Logger::errOut.rdbuf();
        Logger::logOutStreamBuffBackup = Logger::logOut.rdbuf();

        Logger::errOut.rdbuf( std::cerr.rdbuf() );
        Logger::logOut.rdbuf( std::cout.rdbuf() );
    } else {//Redirect stdout/stderr to custom logging/error functionality
        cerrStreamBuffBackup = std::cerr.rdbuf();
        coutStreamBuffBackup = std::cout.rdbuf();

        std::cerr.rdbuf( errOut.rdbuf() );
        std::cout.rdbuf( logOut.rdbuf() );
    }
}
Logger::~Logger() {
    if (HTTP_DEBUG_MODE) {

    } else {//Restore stdout/stderr streambuf
        std::cerr.rdbuf( Logger::cerrStreamBuffBackup );
        std::cout.rdbuf( Logger::coutStreamBuffBackup );
    }
}

If anyone could please help me resolve this, or suggest an alternative method given what I am trying to do, I would be grateful.


Solution

  • std::ostringstream objects inherit the rdbuf() method and I should be able to call the rdbuf() method on the stream objects, passing as an argument a pointer to the std::streambuf to associate with the streams.

    You should in terms of the Liskov substitution principle, but you can't.

    std::basic_stringstream::rdbuf hides both signatures of std::basic_ios::rdbuf(). You are able to call them with some ugly casts, but I think this will have no effect. A stringstream always guarantees to write to a string buffer.