12

I'd like to send data to nowhere, I mean that I don't want to print data in console nor in file, but I need some std::ostream object. How to do that?

iammilind
  • 68,093
  • 33
  • 169
  • 336
scdmb
  • 15,091
  • 21
  • 85
  • 128
  • I'm pretty sure this is a dupe, can't search for it atm though, as I'm on my iPhone. – Xeo Oct 19 '11 at 12:33

5 Answers5

15

I've used:

std::ostream bitBucket(0);

recently without problems, although it was flagged as having some potential problems if you looked at it from a certain angle (see the link below).

Aside: From what I understand (and I'm not entirely sure of this), that call above eventually ends up calling basic_ios::init(0) and, because that's a NULL pointer being passed in, it sets the stream state, as returned by the rdstate() function, to the badbit value.

This in turn prevents the stream from outputting any more information, instead just tossing it away.

The following program shows it in action:

#include <iostream>

int main (void) {
    std::ostream bitBucket(0);
    bitBucket << "Hello, there!" << std::endl;
    return 0;
}

The page where I got it from also had this as a probably-cleaner solution (slightly modified to remove the duplication of my first solution above):

#include <iostream>

class null_out_buf : public std::streambuf {
    public:
        virtual std::streamsize xsputn (const char * s, std::streamsize n) {
            return n;
        }
        virtual int overflow (int c) {
            return 1;
        }
};

class null_out_stream : public std::ostream {
    public:
        null_out_stream() : std::ostream (&buf) {}
    private:
        null_out_buf buf;
};

null_out_stream cnul;       // My null stream.

int main (void) {
    std::cout << std::boolalpha;

    //testing nul

    std::cout << "Nul stream before: " << cnul.fail() << std::endl;
    cnul << "Goodbye World!" << std::endl;
    std::cout << "Nul stream after: " << cnul.fail() << std::endl;
}
Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    what does it mean that you give 0 in constructor? – scdmb Oct 19 '11 at 08:18
  • It (apparently, since I'm not _entirely_ certain of the inner workings) sets the stream state to bad (by calling `init` with a NULL pointer), I believe it won't then attempt to send any more data, instead just tossing it away. Take that with a _big_ grain of salt. – paxdiablo Oct 19 '11 at 08:33
5

The simplest solution is just to output to an unopened std::ofstream (or any other output stream in an error state). This will result in the stream being permanently in an error state. This could be an advantage (<< operators will skip the formatting), but if any code that you can't control checks for errors, and does something particular if they occur, you'll likely have problems.

Otherwise, it's pretty simple to implement a null stream; the only streambuf function you really have to override is overflow. Something like the following should do the trick:

class NulStreambuf : public std::streambuf
{
    char                dummyBuffer[64];
protected:
    virtual int         overflow( int c )
    {
        setp( dummyBuffer, dummyBuffer + sizeof( dummyBuffer ) ) ;
        return (c == EOF) ? '\0' : c ;
    }
};

(The buffer will avoid some unnecessary virtual function calls. On some platforms, this makes a significant difference.)

Then create an output stream which uses it:

class NulOStream : public NulStreambuf, public std::ostream
{
public:
    NulOStream() : std::ostream( this ) {}
};

(The use of inheritance, rather than containment, ensures that the streambuf is fully constructed before being passed to the ostream. This generally isn't necessary in practice, but the standard doesn't seem to authorize passing a not yet constructed streambuf to the constructor of ostream.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
2

Simplest solution: Use a std::stringstream.

#include <sstream>
#include <iostream>

void func(std::ostream& o){
    o << "blatest\n";
}

int main(){
    std::stringstream black_hole;
    func(std::cout);
    func(black_hole);
}

The stringstream will contain the output, but if you don't use it, it's the same as if it was never filled.

Xeo
  • 129,499
  • 52
  • 291
  • 397
  • 11
    Except that the stringstream will still allocate memory, which may be an issue, if the output is large. – tbleher Jun 24 '13 at 16:37
0

Since nobody mentioned it, if it's about suppressing std or error output, you can simply close the corresponding file descriptors (e.g. fclose (stdout) or fclose (stderr)).
That will shup up everything, including things like printf or fprintf (stderr, ...)
So you will indeed keep using the usual cout or cerr, but they will be turned into bit buckets.

kuroi neko
  • 8,479
  • 1
  • 19
  • 43
0

Some suggestions here: http://bytes.com/topic/c/answers/589209-std-null-stream

A good answer from that site:

Use ordinary std::fstream, open it only for writing to required file "/dev/null". It should work.

If you really want to create own stream, just derive it from basic_ostream and simply define your own operator<< to be function which only returns stream reference. You will have to write dummy 'write' and 'put' method too (and all other methods for output).

#include <streambuf>
#include <ostream>

template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
    typename traits::int_type overflow(typename traits::int_type c)
    {
        return traits::not_eof(c); // indicate success
    }
};

template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
    basic_onullstream():
    std::basic_ios<cT, traits>(&m_sbuf),
    std::basic_ostream<cT, traits>(&m_sbuf)
    {
        init(&m_sbuf);
    }

private:
    basic_nullbuf<cT, traits> m_sbuf;
};

typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;

From http://bytes.com/topic/c/answers/428285-null-ostream

GDavid
  • 128
  • 1
  • 2
  • 12
Greg Reynolds
  • 9,736
  • 13
  • 49
  • 60