Re: How to redirect clog to cout and ofstream at the same time?

Discussion in 'C++' started by ksamdev, Sep 10, 2010.

  1. ksamdev

    ksamdev Guest

    On Sep 10, 8:24 am, "Francesco S. Carta" <> wrote:
    > ksamdev <>, on 10/09/2010 06:15:50, wrote:
    >
    > > Hi,

    >
    > > Is is possible to make clog output messages into two output stream
    > > simultaneously, say: cout and ostream?

    >
    > > Unfortunately, ostream::rdbuf(...) allows to set only one at a time.

    >
    > > I'd like to have messages that are sent to clog to be output on the
    > > screen and logged in file at the same time.

    >
    > Consider creating a stream-like "mylog" class and set it to output the
    > data to whatever you like, whenever you insert data into it. Obviously,
    > you should replace all occurrences of "clog" with "mylog", then.
    >
    > --
    >   FSC -http://userscripts.org/scripts/show/59948
    >  http://fscode.altervista.org-http://sardinias.com


    Hmm, are you suggesting something like [*] ?



    [*]

    class MyLog
    {
    public:
    MyLog();

    template<typename T>
    MyLog &operator <<(const T &)
    };

    ....

    template<typename T>
    MyLog &MyLog::eek:perator<<(const T &)
    {
    clog << T;
    cout << T;

    return *this;
    }

    Honestly, I am not quite sure if it will work with <iomanip> since I
    use those a lot. My guess would be: it won't work out of the box.
    ksamdev, Sep 10, 2010
    #1
    1. Advertising

  2. ksamdev

    ksamdev Guest

    On Sep 10, 9:44 am, Stuart Redmann <> wrote:
    > ksamdev on 10/09/2010 wrote:
    > > > > Hi,

    >
    > > > > Is is possible to make clog output messages into two output stream
    > > > > simultaneously, say: cout and ostream?

    >
    > > > > Unfortunately, ostream::rdbuf(...) allows to set only one at a time..

    >
    > > > > I'd like to have messages that are sent to clog to be output on the
    > > > > screen and logged in file at the same time.

    >
    > On Sep 10, Francesco S. Carta wrote:
    >
    > > > Consider creating a stream-like "mylog" class and set it to output the
    > > > data to whatever you like, whenever you insert data into it. Obviously,
    > > > you should replace all occurrences of "clog" with "mylog", then.

    >
    > On 10 Sep. ksamdev wrote:
    >
    >
    >
    >
    >
    > > Hmm, are you suggesting something like [*] ?

    >
    > > [*]

    >
    > > class MyLog
    > > {
    > >   public:
    > >      MyLog();

    >
    > >      template<typename T>
    > >        MyLog &operator <<(const T &)

    >
    > > };

    >
    > > ...

    >
    > > template<typename T>
    > > MyLog &MyLog::eek:perator<<(const T &)
    > > {
    > >   clog << T;
    > >   cout << T;

    >
    > >   return *this;

    >
    > > }

    >
    > > Honestly, I am not quite sure if it will work with <iomanip> since I
    > > use those a lot. My guess would be: it won't work out of the box.- Zitierten Text ausblenden -

    >
    > Add the following lines to MyLog and you should be able to use the
    > manipulators as well:
    >
    >     MyLog& operator<< (std::eek:stream& (__cdecl *_F)(std::eek:stream&))
    >     {
    >       _F (cout);
    >       _F (clog);
    >       return *this;
    >     }
    >     MyLog& operator<< (std::ios& (__cdecl *_F)(std::ios&))
    >     {
    >       _F (cout);
    >       _F (clog);
    >       return *this;
    >     }
    >
    > WARNING: I didn't test this.
    >
    > Regards,
    > Stuart


    __cdecl <- this is something interesting
    ksamdev, Sep 10, 2010
    #2
    1. Advertising

  3. ksamdev <>, on 10/09/2010 07:12:57, wrote:

    > On Sep 10, 8:24 am, "Francesco S. Carta"<> wrote:
    >> ksamdev<>, on 10/09/2010 06:15:50, wrote:
    >>
    >>> Hi,

    >>
    >>> Is is possible to make clog output messages into two output stream
    >>> simultaneously, say: cout and ostream?

    >>
    >>> Unfortunately, ostream::rdbuf(...) allows to set only one at a time.

    >>
    >>> I'd like to have messages that are sent to clog to be output on the
    >>> screen and logged in file at the same time.

    >>
    >> Consider creating a stream-like "mylog" class and set it to output the
    >> data to whatever you like, whenever you insert data into it. Obviously,
    >> you should replace all occurrences of "clog" with "mylog", then.
    >>
    >> --
    >> FSC -http://userscripts.org/scripts/show/59948
    >> http://fscode.altervista.org-http://sardinias.com

    >
    > Hmm, are you suggesting something like [*] ?
    >
    >
    >
    > [*]
    >
    > class MyLog
    > {
    > public:
    > MyLog();
    >
    > template<typename T>
    > MyLog&operator<<(const T&)
    > };
    >
    > ....
    >
    > template<typename T>
    > MyLog&MyLog::eek:perator<<(const T&)
    > {
    > clog<< T;
    > cout<< T;
    >
    > return *this;
    > }
    >
    > Honestly, I am not quite sure if it will work with<iomanip> since I
    > use those a lot. My guess would be: it won't work out of the box.


    First of all, seems that you have been already pointed to working
    solutions that involve setting multiple buffers as you asked, so
    consider this to be a different approach just in case you need it.

    Besides, with this technique, you have the chance to differentiate the
    output for the different streams (you might decide to force a particular
    precision for the on-file logging, for instance).

    WRT what you posted above, as it seems [*], you just need to overload
    operator<<() like this:

    //-------
    #include <iostream>
    #include <iomanip>
    #include <vector>

    using namespace std;

    struct MyLog {
    std::vector<std::eek:stream*> streams;

    template<class T>
    MyLog& operator<<(const T& t) {
    for (size_t i = 0; i < streams.size(); ++i) {
    (*streams) << t;
    }
    return *this;
    }

    MyLog& operator<<(std::eek:stream& (*f) (std::eek:stream&)) {
    for (size_t i = 0; i < streams.size(); ++i) {
    (*streams) << f;
    }
    return *this;
    }
    };


    int main() {
    MyLog mylog;
    mylog.streams.push_back(&cout);

    mylog << "Test Manipulators" << endl;

    /* accepted manipulators */
    mylog << std::boolalpha;
    mylog << std::dec;
    mylog << std::fixed;
    mylog << std::hex;
    mylog << std::internal;
    mylog << std::left;
    mylog << std::noboolalpha;
    mylog << std::noshowbase;
    mylog << std::noshowpoint;
    mylog << std::noshowpos;
    mylog << std::nounitbuf;
    mylog << std::nouppercase;
    mylog << std::eek:ct;
    mylog << std::right;
    mylog << std::scientific;
    mylog << std::showbase;
    mylog << std::showpoint;
    mylog << std::showpos;
    mylog << std::unitbuf;
    mylog << std::uppercase;
    mylog << std::skipws;
    mylog << std::noskipws;
    mylog << std::endl;
    mylog << std::ends;
    mylog << std::flush;
    mylog << std::resetiosflags(std::ios_base::showbase);
    mylog << std::setbase(10);
    mylog << std::setfill(' ');
    mylog << std::setiosflags(std::ios_base::showbase);
    mylog << std::setprecision(10);
    mylog << std::setw(10);

    return 0;
    }
    //-------

    [*] The above is a variation of a class used to build strings on the
    fly, a subject that arose here in the group last year. The solution has
    been contested at the time because, I've been told, the above should not
    work for some of the manipulators. Well. I don't know. I only know that
    MinGW 4.4.0 accepts it without a crease.

    Please see these threads for the discussions that took place at the time:

    http://groups.google.com/group/comp.lang.c /browse_thread/thread/2abb08cc724c70a0/7d872830d84bfd1c

    http://groups.google.com/group/comp.lang.c /browse_thread/thread/fc658b19085bc581/5afe024c2a9927dc

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
    Francesco S. Carta, Sep 11, 2010
    #3
  4. [snip]

    On Sep 10, Stuart Redmann wrote:
    > > Add the following lines to MyLog and you should be able to use the
    > > manipulators as well:

    >
    > >     MyLog& operator<< (std::eek:stream& (__cdecl *_F)(std::eek:stream&))
    > >     {
    > >       _F (cout);
    > >       _F (clog);
    > >       return *this;
    > >     }


    [snip]

    On 10 Sep., ksamdev wrote:

    > __cdecl <- this is something interesting


    Right. __cdecl is Microsoft specific. Apparently they use a different
    calling convention for IO manipulators. I'll find out whether this is
    standard-conformant or not. For standard-conformant code you'll
    probably have to delete __cdecl from the code above (or better put it
    into a #define that expands to __cdecl when compiled on MS Visual C).

    Regards,
    Stuart
    Stuart Redmann, Sep 13, 2010
    #4
    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. Squid Seven

    ofstream * vs. ofstream

    Squid Seven, Jul 13, 2005, in forum: C++
    Replies:
    5
    Views:
    597
    Ivan Johansen
    Jul 14, 2005
  2. Joe Hesse

    Use cout as ofstream object

    Joe Hesse, Sep 26, 2007, in forum: C++
    Replies:
    5
    Views:
    486
    Salt_Peter
    Sep 26, 2007
  3. Replies:
    5
    Views:
    719
    Jim Langston
    Jan 13, 2009
  4. ksamdev
    Replies:
    2
    Views:
    1,192
    ksamdev
    Sep 10, 2010
  5. Jeff Flinn
    Replies:
    0
    Views:
    393
    Jeff Flinn
    Sep 11, 2010
Loading...

Share This Page