null ostream?

A

Angel Tsankov

How do I define a null ostream that inherits publicly std::eek:stream and
ignores anything that would otherwise be output?
 
M

Mark P

Angel said:
How do I define a null ostream that inherits publicly std::eek:stream and
ignores anything that would otherwise be output?

You could create an ofstream that writes to /dev/null
Not portable, but easy :)
 
T

Thomas Tutone

Angel said:
How do I define a null ostream that inherits publicly std::eek:stream and
ignores anything that would otherwise be output?

I cribbed this from c.l.c++ years ago - don't remember the original
author (but it's not me):

#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;

Best regards,

Tom
 
P

peter steiner

try this:

#include <iostream>

struct null_streambuf
: public std::streambuf
{
void overflow(char c)
{
}
};

int main()
{
null_streambuf nullbuf;

// replace buffer of existing stream
std::streambuf * origbuf = std::cout.rdbuf(&nullbuf);
std::cout << "this goes into oblivion";
std::cout.rdbuf(origbuf);

// create null ostream
std::eek:stream out(&nullbuf);
out << "this goes into oblivion too...";
}


-- peter
 
P

peter steiner

to correct myself, Thomas Tutone's version's author hasn't been too
lazy to ignore non-char character traits and the proper return value of
the streambuf::eek:verflow member. use that one. :)
 
A

Angel Tsankov

Thomas Tutone said:
I cribbed this from c.l.c++ years ago - don't remember the original
author (but it's not me):

#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;

Best regards,

Tom

Thanks, Tom! This seems to be exactly what I need:)
 
A

Angel Tsankov

Thomas Tutone said:
I cribbed this from c.l.c++ years ago - don't remember the original
author (but it's not me):

#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;

Best regards,

Tom

May I save the call init(&m_sbuf); in basic_onullstream's ctor as this
same call is made in basic_ostream's ctor?
 
J

John Harrison

Angel said:
May I save the call init(&m_sbuf); in basic_onullstream's ctor as this
same call is made in basic_ostream's ctor?

My preference would be to keep init and change the initialiser list

basic_onullstream()
{
init(&m_sbuf);
}

john
 
A

Angel Tsankov

John Harrison said:
My preference would be to keep init and change the initialiser list

basic_onullstream()
{
init(&m_sbuf);
}

john

Well, I'm not sure this is a good idea, as ctors of virtual bases must
be called by any derived class ctor, right?
 
M

Maxim Yegorushkin

Angel said:
How do I define a null ostream that inherits publicly std::eek:stream and
ignores anything that would otherwise be output?

You can just set the failbit on any ostream. This makes it effectively
ignore all output sent to it until you unset the bit.
 
J

John Harrison

Angel said:
Well, I'm not sure this is a good idea, as ctors of virtual bases must
be called by any derived class ctor, right?

Right, but the code above is exactly equivalent to this

basic_onullstream() : std::basic_ios<cT, traits>()
{
init(&m_sbuf);
}

in other words the default constructor of the virtual base class will be
called automatically if you don't explicitly specify a different
constructor.

john
 
A

Angel Tsankov

Right, but the code above is exactly equivalent to this

basic_onullstream() : std::basic_ios<cT, traits>()
{
init(&m_sbuf);
}

in other words the default constructor of the virtual base class
will be called automatically if you don't explicitly specify a
different constructor.

john

Yes, I totally agree with you on this point. Anyway, could tou tell us
the reasons you prefer to change the initializer list but keep init?
 
J

John Harrison

Yes, I totally agree with you on this point. Anyway, could tou tell us
the reasons you prefer to change the initializer list but keep init?

Nothing deep, it's just when I write code like this

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)
{
}

my compiler warns me about using pointers to as yet unconstructed
objects. If the basic_ios or basic_ostream constructors were to
dereference the pointer it would be undefined behaviour. They don't of
course but my compiler doesn't know that so I get the warning.

john
 
A

Angel Tsankov

Nothing deep, it's just when I write code like this

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)
{
}

my compiler warns me about using pointers to as yet unconstructed
objects. If the basic_ios or basic_ostream constructors were to
dereference the pointer it would be undefined behaviour. They don't
of course but my compiler doesn't know that so I get the warning.

john

What compiler are you using?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top