-->

Properly overload operator << in Boost.Log

2019-06-21 19:03发布

问题:

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.

回答1:

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.


回答2:

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.