I was wondering if there is an easy way that one could create a custom
class that inherits from std::ostream to override the functionality of
operator<<.
Since I work with several processes, I want to avoid some of them to
print information to standard output (or enable that to print
information concurrently). I tried the following but it didn't work:
class Output_strem : public std::ostream {
typedef std::ostream base_type;
public:
Output_strem() : base_type() {}
template <typename T>
std::ostream& operator<<(T t) {
#ifdef MPI
std::ostream& os = *this;
os<<"["<<Parallel_base::rank_<<"] ";
#endif
return *this;
}
};
As you see, nothing is telling the ostream object to print to standard
output. I saw the definition of the cout in the standard library and
it looks like this:
ios_base::Init::Init()
{
if (__gnu_cxx::__exchange_and_add_dispatch(&_S_refcount, 1) == 0)
{
// Standard streams default to synced with "C" operations.
_S_synced_with_stdio = true;
new (&buf_cout_sync) stdio_sync_filebuf<char>(stdout);
// other created objects
// The standard streams are constructed once only and never
// destroyed.
new (&cout) ostream(&buf_cout_sync);
// other created objects
// NB: Have to set refcount above one, so that standard
// streams are not re-initialized with uses of ios_base::Init
// besides <iostream> static object, ie just using <ios> with
// ios_base::Init objects.
__gnu_cxx::__atomic_add_dispatch(&_S_refcount, 1);
}
}
Can someone point me in the right direction?
Thank you all,
aa
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
No, because
1. ostream::operator<< are not virtual, so you can't override them.
2. free operator<< functions are not even memberfunctions, so you can
override them even less.
> Since I work with several processes, I want to avoid some of them to
> print information to standard output (or enable that to print
> information concurrently).
It's not so easy to influence different processes, any changes are always
isolated to one process. I guess you are aware of that, but I just wanted
to mention it explicitly.
> I tried the following but it didn't work:
>
> class Output_strem : public std::ostream {
> typedef std::ostream base_type;
> public:
> Output_strem() : base_type() {}
> template <typename T>
> std::ostream& operator<<(T t) {
> #ifdef MPI
> std::ostream& os = *this;
> os<<"["<<Parallel_base::rank_<<"] ";
> #endif
> return *this;
> }
> };
>
> As you see, nothing is telling the ostream object to print to standard
> output.
[Just a side note here: Try to feed std::endl to the above, it will fail. As
an exercise, try to understand why.]
You can redirect streams:
std::ostream out;
out.rdbuf(std::cout.rdbuf());
out << "foo" << std::endl;
This will print to cout's streambuffer. This streambuffer is responsible for
buffering written characters, conversion from internal characters to
external bytes and for the actual IO.
This is also the place where you can hook in. All you need is a streambuffer
that scans the output data and prepends some additional information before
each line (at least that's how I understand your example code). This
streambuffer then simply delegates the accumulated content to another
streambuffer, i.e. the original one of the stream.
I would suggest you take a look at Boost, which contains a library that e.g.
provides filters etc. I'm pretty sure that you can make use of some of
these but at least they will server as examples with well-written code.
Good luck!
Uli
--
Domino Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
I'm not sure because I do not understand what you want to realize. Even
without grasping what you intend to do your initial approach looks
wrong, because
a) std::ostream does have non-virtual operator<< overloads, some as
members, some as free functions.
b) User-defined classes typically define their own operator<< overloads
accepting either std::ostream or - as function templates - such
overloads accepting basic_ostream<> as first parameter.
This clearly demonstrates that inheriting from std::ostream and
providing some generic operator<< overload cannot solve the problem to
hijack user-defined implementations that are IO inserters.
The main question is: What do you want to realize?
I guess you need to implement your own std::streambuf that you inject
into some ostream. If this is correct, you might want to look into
http://stackoverflow.com/questions/524524/creating-an-ostream
or google by combining 'adapter' with either 'ostream' or 'streambuf'.
HTH & Greetings from Bremen,
Daniel Krügler
It is easy to create a class which sends characters to a different
destination. However, this isn't done by deriving from std::ostream
(well, except for easy creation of an std::ostream, that is) but
rather by deriving a class from std::streambuf and setting up an
std::ostream (possibly in a class derived thereof which only has
a constructor setting up the stream buffer) to use this stream
buffer.
If you want to change the behavior of the actual output operators
you are in general out of luck. For the numeric output operators
of built-in types, you can install a specialized std::locale which
provides a std::num_put<char> and/or a std::numpunct facet.
> Since I work with several processes, I want to avoid some of them to
> print information to standard output (or enable that to print
> information concurrently).
Turning output to standard output off in a process is extremely
easy, though, and doesn't require any new class. Here are a few
options:
1. Pretend that std::ostream had encountered an error, i.e. set
the std::failbit:
std::cout.setstate(std::ios_base::failbit);
2. Remove the stream buffer used by std::cout, e.g.
std::cout.rdbuf(0);
Concurrent writes to a stream are not supported at all and I'm
not aware of any nice way to make it happen. With the upcoming
C++0x (in particular with support for move construction) I
could imagine something which writes to a temporary stream
whose content is sent as one unit to another stream (e.g.
std::cout). However, even this would require some convention
for locking. If you are talking separate processes, you could
set up an output process to which the various standard outputs
are directed (either by operating system level redirects of the
standard output or by some client/server protocol using some
sort of custom stream buffer).
> I tried the following but it didn't work:
>
> class Output_strem : public std::ostream {
Don't derive from std::ostream except to set up a specific stream
buffer in the constructor of the derived class. The derived class
shall in any case not try to overload any of the existing
functions and it can't override them as none of the members of
std::ostream are virtual. Well, the destructor of std::ostream
actually is virtual (which is at least partially my fault; well,
it actually is also kind of correct: you can derive from
std::ostream but you need to know what you are doing and what
shall not do...).
> I saw the definition of the cout in the standard library and
> it looks like this:
>
> ios_base::Init::Init()
> {
Actually, this isn't the definition of std::cout but rather some
fairly horrible hack to make sure that std::cout is constructed
before it is possibly used. There are [much] better way to
achieve the same effect without requiring every translation unit
which includes <iostream> to be loaded during start-up. My
preferred approach to this are
1. Just put the definition of std::cout in the library into an
appropriate location! Yes, this ain't portable but a lot of
things about the implementation of the standard library aren't
portable.
2. Put the definition of std::cout into its own shared library
and have std::cout be constructed/destructed by the shared
library's _ini() and _fini() functions. Since this is part of
the C++ implementation, this library can be added
transparently (like -lstdc++ already is added when using g++)
In any case, what std::ios_base::Init::Init() does internally is
nobody's but the standard C++ library's implementer's business.
... and it can do things a user won't be able to do either.