inheriting from ostream to customize standard output

Discussion in 'C++' started by aaragon, Mar 29, 2011.

  1. aaragon

    aaragon Guest

    Hi everybody,

    I was wondering if there is an easy way that one could create a custom
    class that inherits from std::eek:stream 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::eek:stream {

    typedef std::eek:stream base_type;

    public:

    Output_strem() : base_type() {}


    template <typename T>
    std::eek:stream& operator<<(T t) {

    #ifdef MPI

    std::eek:stream& 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
    aaragon, Mar 29, 2011
    #1
    1. Advertising

  2. aaragon

    Larry Evans Guest

    On 03/29/11 05:48, aaragon wrote:
    > Hi everybody,
    >
    > I was wondering if there is an easy way that one could create a custom
    > class that inherits from std::eek:stream 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).


    Boost iostreams enables you to install a filter in a streambuf:

    http://www.boost.org/doc/libs/1_46_1/libs/iostreams/doc/index.html

    Maybe you could install a filtering streambuf in cout to do what you
    want; however, since I've never done any kind of filtering such as
    you describe, I can't provide any concrete suggestions on how to do
    that.

    -regards,
    Larry
    Larry Evans, Mar 30, 2011
    #2
    1. Advertising

  3. aaragon

    aaragon Guest

    On Mar 30, 3:23 am, Larry Evans <> wrote:
    > On 03/29/11 05:48, aaragon wrote:
    >
    > > Hi everybody,

    >
    > > I was wondering if there is an easy way that one could create a custom
    > > class that inherits from std::eek:stream 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).

    >
    > Boost iostreams enables you to install a filter in a streambuf:
    >
    >  http://www.boost.org/doc/libs/1_46_1/libs/iostreams/doc/index.html
    >
    > Maybe you could install a filtering streambuf in cout to do what you
    > want; however, since I've never done any kind of filtering such as
    > you describe, I can't provide any concrete suggestions on how to do
    > that.
    >
    > -regards,
    >  Larry


    Thanks Larry for your reply. I ended up doing the following:

    class Output_stream : public std::eek:stream {

    typedef std::eek:stream base_type;

    size_t id_;

    public:


    Output_stream(const std::eek:stream& os = cout, size_t id =
    size_t(-1)) : base_type(os.rdbuf()), id_(id) {}

    template <typename T>
    std::eek:stream& operator<<(typename
    Type_traits<T>::parameterType t) {

    #ifdef MPI

    std::eek:stream& os = *this;

    if (id_ != size_t(-1))
    if (Parallel_base::rank_ != id_)
    return *this;

    os<<"["<<Parallel_base::rank_<<"] ";

    #endif

    return base_type::eek:perator<<(t);
    }

    };

    It seems to work fine, only that it doesn't work because of the
    template function is not being called. I need to figure out why.

    Alejandro
    aaragon, Mar 30, 2011
    #3
  4. aaragon

    Larry Evans Guest

    On 03/30/11 01:54, aaragon wrote:
    > On Mar 30, 3:23 am, Larry Evans <> wrote:
    >> On 03/29/11 05:48, aaragon wrote:
    >>
    >>> Hi everybody,

    >>
    >>> I was wondering if there is an easy way that one could create a custom
    >>> class that inherits from std::eek:stream 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).

    >>
    >> Boost iostreams enables you to install a filter in a streambuf:
    >>
    >> http://www.boost.org/doc/libs/1_46_1/libs/iostreams/doc/index.html
    >>
    >> Maybe you could install a filtering streambuf in cout to do what you
    >> want; however, since I've never done any kind of filtering such as
    >> you describe, I can't provide any concrete suggestions on how to do
    >> that.
    >>
    >> -regards,
    >> Larry

    >
    > Thanks Larry for your reply. I ended up doing the following:
    >
    > class Output_stream : public std::eek:stream {
    >
    > typedef std::eek:stream base_type;
    >
    > size_t id_;
    >
    > public:
    >
    >
    > Output_stream(const std::eek:stream& os = cout, size_t id =
    > size_t(-1)) : base_type(os.rdbuf()), id_(id) {}
    >
    > template <typename T>
    > std::eek:stream& operator<<(typename
    > Type_traits<T>::parameterType t) {
    >
    > #ifdef MPI
    >
    > std::eek:stream& os = *this;
    >
    > if (id_ != size_t(-1))
    > if (Parallel_base::rank_ != id_)
    > return *this;
    >
    > os<<"["<<Parallel_base::rank_<<"] ";
    >
    > #endif
    >
    > return base_type::eek:perator<<(t);
    > }
    >
    > };
    >
    > It seems to work fine, only that it doesn't work because of the
    > template function is not being called. I need to figure out why.
    >
    > Alejandro


    Hi Alejandro,

    I think the problem is something cused by "nondeduced context"
    (I may not be getting the term exactly right, but it's something
    like that.) The problem is the compiler cannot decide which type,
    T, to use when instantiating operator<<. To illustrate the problem,
    a simplified version of your code attached.

    The problem occurs when the #if on line 43 is:

    #if 1

    which causes the:

    operator<<(T::U const&)

    code to be used. Now, if there are a T1 and T2 both with the
    same value for U, then how can the compiler know which T to
    choose? For example, in the attached code, buth C<1> and C<2>
    have the same value for their U, which is B. Now, I know what
    you're probably thinking, "Well it's obvious from
    the call site, which C<I> to use. I had the exact same question:

    http://groups.google.com/group/comp...ondeduced context workaround#2cb76b2c61eb37ae

    See if reading that thread can clear things up. I still have trouble
    with really understanding since it seems to obvious from looking
    at the code:

    a<<C<1>::B()

    that C<1> should be the T in the operator<< template. Hmmm..
    wait, but then what about:

    a<<B()

    which C<I> should be used then, Oh, but then, in this case
    there base::eek:perator<< would be used. I guess the compiler
    would have to have too much context information that the
    writers decided just to disallow this.

    Confused? You're not alone?

    HTH.

    -Larry
    Larry Evans, Mar 30, 2011
    #4
  5. aaragon

    James Kanze Guest

    On Mar 29, 11:48 am, aaragon <> wrote:
    > I was wondering if there is an easy way that one could create
    > a custom class that inherits from std::eek:stream to override the
    > functionality of operator<<.


    No, thank goodness. The behavior of the operator<< is part of
    the contract of ostream, and too much other code counts on it.
    What you can do is define your own streaming class; when
    appropriate, it could delegate to an ostream.

    > 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::eek:stream {


    > typedef std::eek:stream base_type;
    > public:
    > Output_strem() : base_type() {}


    > template <typename T>
    > std::eek:stream& operator<<(T t) {


    > #ifdef MPI
    > std::eek:stream& os = *this;
    > os<<"["<<Parallel_base::rank_<<"] ";
    > #endif
    > return *this;
    > }
    > };


    > Can someone point me in the right direction?


    Use delegation instead of inheritance.

    --
    James Kanze
    James Kanze, Apr 3, 2011
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Parity
    Replies:
    2
    Views:
    374
    Stephen Howe
    Aug 13, 2003
  2. Trevor
    Replies:
    2
    Views:
    514
  3. enzo

    inheriting ostream

    enzo, Jan 16, 2004, in forum: C++
    Replies:
    3
    Views:
    391
    Andrey Tarasevich
    Jan 17, 2004
  4. AJG
    Replies:
    1
    Views:
    606
    James Kanze
    Jun 29, 2008
  5. Replies:
    2
    Views:
    1,902
Loading...

Share This Page