Standard no-op output stream

C++Iostream

C++ Problem Overview


Is there a way to create an ostream instance which basically doesn't do anything ?

For example :

std::ostream dummyStream(...);
dummyStream << "Nothing will be printed";

I could just create an ostringstream, but data will be buffered (and I really don't want to make anything with them, so it adds a useless overhead).

Any idea ?

[edit] Found this related question which suits my needs. However, I think it could be useful to have a answer saying how to create a valid (no badbit) output stream with standard c++.

C++ Solutions


Solution 1 - C++

You need a custom streambuf.

class NullBuffer : public std::streambuf
{
public:
  int overflow(int c) { return c; }
};

You can then use this buffer in any ostream class

NullBuffer null_buffer;
std::ostream null_stream(&null_buffer);
null_stream << "Nothing will be printed";

streambuf::overflow is the function called when the buffer has to output data to the actual destination of the stream. The NullBuffer class above does nothing when overflow is called so any stream using it will not produce any output.

Solution 2 - C++

If this is to disable logging output, your dummyStream would still cause arguments to be evaluated. If you want to minimize impact when logging is disabled, you can rely on a conditional, such as:

#define debugStream \
    if (debug_disabled) {} \
    else std::cerr

So if you have code like:

debugStream << "debugging output: " << foo() << std::endl;

No arguments will be evaluated if debug_disabled is true.

Solution 3 - C++

The basic method voor new stream classes is:

  1. Derive a class from std::streambuf;
  2. Override the virtual functions in that class. This is where the real work is done. In your case, empty implementations should be good enough.
  3. Derive a class from std::ostream with one member, your streambuf class.
  4. The constructor of your streamclass should forward the pointer to that member to the base constructor of std::ostream.

I'm afraid you won't get rid of the formatting step, though.

Hopefully this gives you some pointers; I don't have the time to expand this into a full answer, sorry.

Update: See john's answer for details.

Solution 4 - C++

For runtime-controllable redirection of log messages, a self-contained solution combining the ideas of john and Sjoerd:

class DebugStream {
private:
    class NullStream : public std::ostream {
    private:
        class NullBuffer : public std::streambuf {
        public:
            int overflow(int c) override { return c; }
        } buffer_;
    public:
        NullStream() : std::ostream(&buffer_) {}
    } null_;

    std::ostream &output_;
    bool enabled_;

public:
    DebugStream(std::ostream &output = std::cout) : output_(output), enabled_(false) {}
    void enable(const bool enable) { enabled_ = enable; }

    template <typename T> std::ostream& operator<<(const T &arg) {
        if (enabled_) return output_ << arg;
        else return null_ << arg;
    }
};

extern DebugStream debug_stream;
#define TRACE_ENABLE(x) debug_stream.enable(x)
#define TRACELN(x) debug_stream << x << std::endl
#define TRACE(x) debug_stream << x

Then you can do stuff like:

TRACELN("The value of x is " << x " and the value of y is " << y);

It would also be easy to just remove the trace statements from a release version completely with #define the trace macros to empty statements.

You still need to define debug_stream somewhere global, though.

Solution 5 - C++

If you are concerned about the overhead of your debugger then you can write a very simple code to void out your debug messages on compilation. This is what I use for my c++ programs.

#include <iostream>
#define DEBUGGING // Define this in your config.h or not.
#ifdef DEBUGGING
/*
 * replace std::cout with your stream , you don't need to
 * worry about the context since macros are simply search
 * and replace on compilation.
 */
#define LOG_START std::cout <<
#define LOG_REDIR <<
#define LOG_END   << std::endl;
#else
#define LOG_START if(0){(void)
#define LOG_REDIR ;(void)
#define LOG_END   ;}
#endif // DEBUGGING

int main(){
LOG_START "This is a log message " LOG_REDIR "Still a log message." LOG_END;
return 0;
}

Now when making your project , check if the user wants to disable the logging , if so , just undefine the DEBUGGING macro or whatever macro you choose to check for.

Now your code will be optimized by the compiler , Because when anything is voided , it will not be included in the resulting binary(most of the time) , making the binary production ready.

Solution 6 - C++

I needed a null stream that was of type ostream so I did something like this:

struct NullStream: public stringstream {
   NullStream(): stringstream() {}
};

template<typename T>
void operator<<(const NullStream&, const T&) {}

Application code:

NullStream ns;
ostream &os = ns;
os << "foo";

The real issue is all the public methods that I inherited but don't care about so I just didn't bother overriding them.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMa&#235;l NisonView Question on Stackoverflow
Solution 1 - C++johnView Answer on Stackoverflow
Solution 2 - C++jxhView Answer on Stackoverflow
Solution 3 - C++SjoerdView Answer on Stackoverflow
Solution 4 - C++neuviemeporteView Answer on Stackoverflow
Solution 5 - C++antonyjrView Answer on Stackoverflow
Solution 6 - C++solstice333View Answer on Stackoverflow