如何为 boost log 和自定义类型定义输出流运算符

And*_*ojc 4 c++ templates stream-operators boost-log

我能够为一个简单的结构定义输出流运算符,但不能为 std::array 定义输出流运算符。以下代码无法编译。出了什么问题,我该如何解决?

\n\n
#include <array>\n#include <iostream>\n#include <boost/log/core.hpp>\n#include <boost/log/trivial.hpp>\n\nusing hash_t = std::array< unsigned char, 32 >;\n\nstd::ostream& operator<< ( std::ostream& os, hash_t const& arr )\n{\n    os << "ole!";\n    return os;\n}\n\nint main(int, char*[])\n{\n    hash_t arr;\n    std::cerr << arr << std::endl; // complies cleanly\n    BOOST_LOG_TRIVIAL(debug) << arr; // Error\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

错误就来了。

\n\n

GCC(增强 1.55,gcc-4.9.2):

\n\n
In file included from /usr/include/boost/log/sources/record_ostream.hpp:31:0,\n                 from /usr/include/boost/log/trivial.hpp:23,\n                 from trival.cpp:4:\n/usr/include/boost/log/utility/formatting_ostream.hpp: In instantiation of \xe2\x80\x98boost::log::v2s_mt_posix::basic_formatting_ostream<CharT, TraitsT, AllocatorT>& boost::log::v2s_mt_posix::operator<<(boost::log::v2s_mt_posix::basic_formatting_ostream<CharT, TraitsT, AllocatorT>&, const T&) [with CharT = char; TraitsT = std::char_traits<char>; AllocatorT = std::allocator<char>; T = std::array<unsigned char, 32ul>]\xe2\x80\x99:\ntrival.cpp:18:30:   required from here\n/usr/include/boost/log/utility/formatting_ostream.hpp:710:19: error: cannot bind \xe2\x80\x98boost::log::v2s_mt_posix::basic_formatting_ostream<char>::ostream_type {aka std::basic_ostream<char>}\xe2\x80\x99 lvalue to \xe2\x80\x98std::basic_ostream<char>&&\xe2\x80\x99\n     strm.stream() << value;\n                   ^\nIn file included from /usr/include/c++/4.9/iostream:39:0,\n                 from trival.cpp:2:\n/usr/include/c++/4.9/ostream:602:5: note: initializing argument 1 of \xe2\x80\x98std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = std::array<unsigned char, 32ul>]\xe2\x80\x99\n     operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)\n
Run Code Online (Sandbox Code Playgroud)\n\n

Clang 错误(Boost 1.64,clang-800.0.42.1):

\n\n
In file included from /usr/local/include/boost/log/trivial.hpp:23:\nIn file included from /usr/local/include/boost/log/sources/record_ostream.hpp:36:\n/usr/local/include/boost/log/utility/formatting_ostream.hpp:878:19: error: invalid operands to binary expression (\'ostream_type\' (aka\n      \'basic_ostream<char, std::__1::char_traits<char> >\') and \'std::__1::array<unsigned char, 32>\')\n    strm.stream() << value;\n    ~~~~~~~~~~~~~ ^  ~~~~~\n/usr/local/include/boost/log/sources/record_ostream.hpp:390:51: note: in instantiation of function template specialization\n      \'boost::log::v2_mt_posix::operator<<<boost::log::v2_mt_posix::basic_formatting_ostream<char, std::__1::char_traits<char>, std::__1::allocator<char> >,\n      std::__1::array<unsigned char, 32> >\' requested here\n    static_cast< formatting_ostream_type& >(strm) << value;\n                                                  ^\n/Users/adam/GitPen/BoostLog/trival/trival.cpp:18:27: note: in instantiation of function template specialization\n      \'boost::log::v2_mt_posix::operator<<<boost::log::v2_mt_posix::basic_record_ostream<char>, std::__1::array<unsigned char, 32> >\' requested here\n        BOOST_LOG_TRIVIAL(debug) << arr;\n
Run Code Online (Sandbox Code Playgroud)\n

And*_*dyG 5

您可能不喜欢这个答案。

为了让它现在正常工作,您需要将您的添加operator<<namespace std

namespace std{
   std::ostream& operator<< ( std::ostream& os, const hash_t& arr )
   {/*...*/}
}
Run Code Online (Sandbox Code Playgroud)

由于 ADL 的工作原理,它只会考虑以下operator<<领域及其专业化:namespace std

你不会喜欢它,因为添加这个函数namespace std是不合法的:

[命名空间.std]

如果 C++ 程序将声明或定义添加到名称空间std或名称空间 std 中的名称空间,则其行为是未定义的,除非另有说明。仅当声明依赖于用户定义类型并且专门化满足原始模板的标准库要求且未明确禁止时,程序才可以将任何标准库模板的模板专门化添加到命名空间 std。

也许最简单的事情就是继承(而不做其他任何事情)类型std

struct hash_t : std::array< unsigned char, 32 >{};
Run Code Online (Sandbox Code Playgroud)