Standard No-Op Output Stream

Standard no-op output stream

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.

Implementing a no-op std::ostream

To prevent the operator<<() invocations from doing formatting, you should know the streamtype at compile-time. This can be done either with macros or with templates.

My template solution follows.

class NullStream {
public:
void setFile() { /* no-op */ }
template<typename TPrintable>
NullStream& operator<<(TPrintable const&)
{ return *this; } /* no-op */
}

template<class TErrorStream> // add TInfoStream etc
class Logger {
public:
TErrorStream& errorStream() {
return m_errorStream;
}

private:
TErrorStream m_errorStream;
};

//usage
int main() {
Logger<std::ofstream> normal_logger; // does real output
normal_logger.errorStream().open("out.txt");
normal_logger.errorStream() << "My age is " << 19;

Logger<NullStream> null_logger; // does zero output with zero overhead
null_logger.errorStream().open("out.txt"); // no-op
null_logger.errorStream() << "My age is " << 19; // no-op
}

Since you have to do this at compile-time, it is of course quite inflexible.

For example, you cannot decide the logging level at runtime from a configuration file.

Is there a null std::ostream implementation in C++ or libraries?

If you have boost, then there's a null ostream & istream implementation available in boost/iostreams/device/null.hpp . The gist of it:

#include "boost/iostreams/stream.hpp"
#include "boost/iostreams/device/null.hpp"
...
boost::iostreams::stream< boost::iostreams::null_sink > nullOstream( ( boost::iostreams::null_sink() ) );
...

How to properly reroute output (away from std::cout)?

I have heard several times, that one should avoid plain writes to std::cout. Is this correct?

No. It is accepted practice to write output to the standard output stream - unless you're in some embedded setting, or using an exotic OS where output is handled very differently.

The operating system and other processes will expect output to be written to that stream, or to whatever it represents (e.g. the standard output file handle on Unix-like systems).

What I came up with so far is this [piece of code here]

Well,

  1. There are several popular logging libraries for C++. Here's a question about that over at SoftwareRecs.SX. No need to re-invenet the wheel if what you want is to do logging.
  2. As @largest_prime_is_463035818 suggests in their comment, it's often good enough to just pass around an std::ostream and write to that. And when you want to not write anywhere - that's possible too; read these SO questions:
  • Standard no-op output stream
  • Printing to nowhere with ostream
Having said all this - there are some cases in which you might legitimately want to have std::cout itself be redirected to print somewhere else. I don't think that's covered by the standard, though.

Is there a Null OutputStream in Java?

Since Java 11, there is a static utility that does exactly what you need, a static factory method OutputStream.nullOutputStream():

Returns a new OutputStream which discards all bytes. The returned stream is initially open. The stream is closed by calling the close() method. Subsequent calls to close() have no effect.

Default NULL value for an ofstream

I want applications that were using myfun to still work with no modifications.

If so, use an ofs with default nullptr

int myfun(const int a, ofstream *ofs = nullptr)
{
if (ofs != nullptr)
{
// (*ofs) << ... ;
}

// ...
}

You can't use a reference parameter ofstream& ofs for such function because a reference cannot be null.

Does ostringstream object need to be cleared?

Obviously when you keep inserting data in the stream it'll consume more memory, which at some point can be a lot.

Clearing it will prevent that.



Related Topics



Leave a reply



Submit