Properly overload operator << in Boost.Log
Asked Answered
N

2

6

In the Boost.Log documentation, it is said that

Note

The library uses basic_formatting_ostream stream type for record formatting, so when customizing attribute value formatting rules the operator<< must use basic_formatting_ostream instead of std::ostream.

However, throughout the documentation, all I see is overloading operator << on std::ostream rather than basic_formatting_ostream in the example code. For example, see the overload for the custom type severity_level here.

According to my tests, the overloads on std::ostream and basic_formatting_ostream both worked fine. So, I'm wondering what are the advantages of overloading on one instead of the other.

Niemeyer answered 2/10, 2015 at 8:2 Comment(1)
The advantage of using std::ostream should be pretty obvious: You can use it for "normal" output as well. :)Inkle
T
4

There is no problems in overloading just operator << (std::ostream&, ...), since formatting_ostream has

template< typename CharT, typename TraitsT, typename AllocatorT, typename T >
inline basic_formatting_ostream< CharT, TraitsT, AllocatorT >&
operator<< (basic_formatting_ostream< CharT, TraitsT, AllocatorT >& strm, T const& value)
{
    strm.stream() << value;
    return strm;
}

where stream() returns std::ostream&. If you overload operator << with first arg formatting_ostream, than this can be used only with boost::log, if you overload for std::ostream&, then this can be used for boost::log and for another output.

Quote from header file:

 * This stream wrapper is used by the library for log record formatting. It implements the standard string stream interface
 * with a few differences:
 *
 * \li It does not derive from standard types <tt>std::basic_ostream</tt>, <tt>std::basic_ios</tt> and <tt>std::ios_base</tt>,
 *     although it tries to implement their interfaces closely. There are a few small differences, mostly regarding <tt>rdbuf</tt>
 *     and <tt>str</tt> signatures, as well as the supported insertion operator overloads. The actual wrapped stream can be accessed
 *     through the <tt>stream</tt> methods.
 * \li By default, \c bool values are formatted using alphabetical representation rather than numeric.
 * \li The stream supports writing strings of character types different from the stream character type. The stream will perform
 *     character code conversion as needed using the imbued locale.
 * \li The stream operates on an external string object rather than on the embedded one. The string can be attached or detached
 *     from the stream dynamically.
 *
 * Although <tt>basic_formatting_ostream</tt> does not derive from <tt>std::basic_ostream</tt>, users are not required to add
 * special overloads of \c operator<< for it since the stream will by default reuse the operators for <tt>std::basic_ostream</tt>.
 * However, one can define special overloads of \c operator<< for <tt>basic_formatting_ostream</tt> if a certain type needs
 * special formatting when output to log.
Trough answered 2/10, 2015 at 8:5 Comment(5)
But inserting into basic_formatting_ostream seems to do more work than inserting into std::ostream. For example, see the overloaded operator << that basic_formatting_ostream has provided for const char*.Niemeyer
@Niemeyer nope, basic_formatting_ostream just implement interface of basic_ostream as close as possible.Trough
So, the Boost.Log documentation is just outdated or what?Niemeyer
@Niemeyer no... Probably they mean, that for just record_formatting you should write formatting_ostream, if format for log should be different from "normal" output.Trough
basic_formatting_ostream doesn't do more work for output that is already supported by std::ostream. The wrapper either forwards the operators to the std::ostream-specific ones, or takes a shortcut, knowing that the output will end up in a string anyway, so, if anything, it should perform faster in those cases. The docs are correct.Lindseylindsley
P
0

If you only overload operator<<(std::ostream), it will work for every stream output, including that to basic_formatting_ostream. If you only overload operator<<(basic_formatting_ostream) it will only work for output to that type of stream.

However, you may want to overload both, for example, if you want to provide different or more information (such as the address of an object) to the log.

Pinnacle answered 2/10, 2015 at 8:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.