Curt Arnold wrote:
On Dec 21, 2004, at 7:12 PM, Christopher Smith wrote:
If it isn't derived from std::ios_base, then manipulators like std::width etc can't be applied.

Actually, I believe my delegation based approach to doing logger streams did work just fine with IO maniplulators. It did ignore them if the stream wasn't enabled just like everything else (which I think is probably the right thing to do), but even that could be changed with some template specializations for manipulators.

We disagree on skipping manipulators applied when the threshold isn't reached. My opinion is that setting the threshold should only affect whether messages appear in the log or not, it should not affect the content of the messages. If you skip manipulators when the threshold isn't satisfied, then some aspect (say field width) on a particular message might vary with the threshold.

With the normal idiom for logstreams you would want different streams for each log level which would avoid this issue entirely.


Regardless it would seem necessary to use something like iostate savers to ensure you didn't leave the stream in an unexpected state. For example, if you have two methods:

Foo::bar() {
        logstream << getCount() << LOG4CXX_ENDMSG;
        //.. stuff
}

Foo::baz() {
        boost::io::ios_flags_saver ifs(logstream);
        logstream << std::hex << getPointer() << LOG4CXX_ENDMSG;
        //.. stuff
}

Now, if you remove ifs from Foo::baz(), then the format of getCount() in Foo::bar() will depend on whether Foo::baz() was called previously, which is even worse than it being impacted by what log level you have things set at. Once you are using ifs consistently, applying manipulators regardless of log levels just becomes a waste of CPU cycles and a source of additional code branching.

In general, if you weren't using logstreams and were instead manually using ostreams, it'd be very odd to have your I/O manipulators behave as you are suggesting. Which seems more natural:

if (logger.isInfoEnabled()) {
logstream << "We have: " << getCount() << " floats at: " << std::hex << getPointer() << LOG4CXX_ENDMSG;
}


or:

if (logger.isInfoEnabled()) {
        logstream << "We have: " << getCount() << " floats at: ";
}

logstream << std::hex;

if (logger.isInfoEnabled()) {
        logstream << getPointer() << LOG4CXX_ENDMSG;
}

I would be willing to have a cook-off on the implementation.
However, the time is wrong to do that while the core is still flaky from
> the recent Unicode rework.

Agreed.

I not even totally opposed to providing two different flavors of logging streams, though ideally we could keep the semantics as close as possible.

My point was though, regardless of which implementation we go with, the I/O manipulators can be setup to behave as per either approach. Indeed, if we *really* wanted to give people a choice of in the matter we could simply use a policy class. Heck, in theory we could make the "inheritence-vs-delegation" approach work that way as well, although that might be just a tad too unwieldy.


--Chris

Reply via email to