在Boost.Log中正确地重载运算符<<

6
Boost.Log文档中提到:

注意

该库使用basic_formatting_ostream流类型进行记录格式化,因此当自定义属性值格式化规则时,operator<<必须使用basic_formatting_ostream而不是std::ostream

然而,在整个文档中,我看到的都是在示例代码中对std::ostream进行重载而不是basic_formatting_ostream。例如,请参见自定义类型severity_level这里的重载。

根据我的测试,对于std::ostreambasic_formatting_ostream的重载都可以正常工作。因此,我想知道在其中一个上进行重载的优点是什么。


1
使用std::ostream的优点应该非常明显:您也可以将其用于“正常”输出。 :) - Some programmer dude
2个回答

4

只要重载operator << (std::ostream&, ...)formatting_ostream就没有问题。

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;
}

stream()函数返回std::ostream&。如果你重载了第一个参数为formatting_ostreamoperator <<,那么只能与boost::log一起使用;如果你重载了std::ostream&,那么可以用于boost::log和其他输出。

引用头文件中的一句话:

 * 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.

但是将内容插入到 basic_formatting_ostream 中似乎比将其插入到 std::ostream 中要多做更多的工作。例如,查看 basic_formatting_ostreamconst char* 提供的重载 operator << - Lingxi
@Lingxi 不是的,basic_formatting_ostream 只是尽可能地实现了 basic_ostream 的接口。 - ForEveR
那么,Boost.Log文档只是过时了吗? - Lingxi
@Lingxi 不是... 可能他们的意思是,如果只是记录格式化,你应该编写 formatting_ostream,如果日志的格式与“正常”输出不同。 - ForEveR
basic_formatting_ostream 对于已经被 std::ostream 支持的输出不会再进行更多的工作。这个包装器要么将操作转发到 std::ostream 特定的操作中,要么采取一些快捷方式,因为它知道输出最终会进入字符串中,所以在这些情况下,如果有什么问题,它应该更快地执行。文档是正确的。 - Andrey Semashev

0

如果你只重载 operator<<(std::ostream),它将适用于所有的流输出,包括 basic_formatting_ostream。如果你只重载 operator<<(basic_formatting_ostream),它只适用于该类型的流输出。

然而,你可能想要同时重载两者,例如,如果你想要向日志提供不同或更多的信息(如对象的地址)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接