You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4cxx-user@logging.apache.org by Rhys Ulerich <rh...@gmail.com> on 2009/12/18 23:08:10 UTC

Using log4cxx::logstream in generic programming

Hi all,

I'd like to be able to use log4cxx::logstream instances within generic
programming.  My goal is pass log4cxx::logstream instances into
templated code expecting basic_ostream instances and have everything
work out.

I've run into two problems.

First, there's no generic way to use std::endl for both
log4cxx::logstream and std::basic_ostream.  Here's a test case against
log4cxx 0.10.0 that illustrates the difficulty:

#include <iostream>
#include <log4cxx/logger.h>
#include <log4cxx/stream.h>

template< typename OStream >
void test_it(OStream & os)
{
    // std::endl<Elem,Tr> can be deduced for std::cout argument
    // std::endl<Elem,Tr> cannot be deduced for log4cxx::logstream argument
    os << "Foo" << std::endl;

    // std::endl<char,std::traits<char> > works for std::cout and
    // log4cxx::logstream
    os << "Bar" << std::endl<char, std::char_traits<char> >;

    // std::endl<typename OStream::char_type, std::char_traits<typename
    // OStream::char_type> works for std::cout but does not work for
    // log4cxx::logstream due to no char_type typedef
    os << "Baz" << std::endl<typename OStream::char_type,
std::char_traits<typename OStream::char_type> >;
}

int main(int argc, char* argv[]) {

    test_it(std::cout);

    log4cxx::LoggerPtr logger = log4cxx::Logger::getRootLogger();
    log4cxx::logstream logstream(logger, log4cxx::Level::getInfo());

    test_it(logstream);

    return 0;
}

I expect that at least the "Baz" line works for both std::cout and
log4cxx::logbase, and ideally the "Foo' line would too.  At least for
the "Baz" case it occurs because log4cxx::logstream lacks typedefs a
la basic_ostream
(http://www.dinkumware.com/manuals/default.aspx?manual=compleat&page=ostream.html#basic_ostream).
 I'm not sure if the "Foo" case could be made to work.  If the "Baz"
case worked it might just require adding a template declarations to
log4cxx/stream.h that attempts to use the char_type and traits_type
typedef to fix the appropriate std::endl template.

Second, even if the first part did work, it seems that without the
magic log4cxx_base::endmsg manipulator that the messages are never
written.  This is much less than generic, and I'd like to have
std::endl take the role of log4stream_base::endmsg whenever it is
encountered.  From looking at Stroustrup's C++ programming language
section 21.4.6 I don't see how to intercept the single std::endl
manipulator and cause it to insert a log4stream_base::endmsg.  I could
be missing something.

Any help appreciated,
Rhys