Я смог определить оператор выходного потока для простой структуры, но не для std :: array. Следующий код не компилируется. Что не так и как я могу это исправить?
#include <array>
#include <iostream>
#include <boost/log/core.hpp>
#include <boost/log/trivial.hpp>
using hash_t = std::array< unsigned char, 32 >;
std::ostream& operator<< ( std::ostream& os, hash_t const& arr )
{
os << "ole!";
return os;
}
int main(int, char*[])
{
hash_t arr;
std::cerr << arr << std::endl; // complies cleanly
BOOST_LOG_TRIVIAL(debug) << arr; // Error
return 0;
}
Здесь идут ошибки.
GCC (повышение 1.55, gcc-4.9.2):
In file included from /usr/include/boost/log/sources/record_ostream.hpp:31:0,
from /usr/include/boost/log/trivial.hpp:23,
from trival.cpp:4:
/usr/include/boost/log/utility/formatting_ostream.hpp: In instantiation of ‘boost::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>]’:
trival.cpp:18:30: required from here
/usr/include/boost/log/utility/formatting_ostream.hpp:710:19: error: cannot bind ‘boost::log::v2s_mt_posix::basic_formatting_ostream<char>::ostream_type {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
strm.stream() << value;
^
In file included from /usr/include/c++/4.9/iostream:39:0,
from trival.cpp:2:
/usr/include/c++/4.9/ostream:602:5: note: initializing argument 1 of ‘std::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>]’
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
Ошибка лягушки (повышение 1.64, clang-800.0.42.1):
In file included from /usr/local/include/boost/log/trivial.hpp:23:
In file included from /usr/local/include/boost/log/sources/record_ostream.hpp:36:
/usr/local/include/boost/log/utility/formatting_ostream.hpp:878:19: error: invalid operands to binary expression ('ostream_type' (aka
'basic_ostream<char, std::__1::char_traits<char> >') and 'std::__1::array<unsigned char, 32>')
strm.stream() << value;
~~~~~~~~~~~~~ ^ ~~~~~
/usr/local/include/boost/log/sources/record_ostream.hpp:390:51: note: in instantiation of function template specialization
'boost::log::v2_mt_posix::operator<<<boost::log::v2_mt_posix::basic_formatting_ostream<char, std::__1::char_traits<char>, std::__1::allocator<char> >,
std::__1::array<unsigned char, 32> >' requested here
static_cast< formatting_ostream_type& >(strm) << value;
^
/Users/adam/GitPen/BoostLog/trival/trival.cpp:18:27: note: in instantiation of function template specialization
'boost::log::v2_mt_posix::operator<<<boost::log::v2_mt_posix::basic_record_ostream<char>, std::__1::array<unsigned char, 32> >' requested here
BOOST_LOG_TRIVIAL(debug) << arr;
Вам может не понравиться этот ответ.
Чтобы заставить это работать должным образом в данный момент, вам нужно добавить свой operator<<
в namespace std
:
namespace std{
std::ostream& operator<< ( std::ostream& os, const hash_t& arr )
{/*...*/}
}
из-за того, как работает ADL, он будет рассматривать только operator<<
и его специализация в namespace std
Вам не понравится, потому что добавление этой функции в namespace std
это не законно
Поведение программы на C ++ не определено, если она добавляет объявления или определения в пространство имен
std
или к
пространство имен в пространстве имен std, если не указано иное. Программа может добавить шаблон специализации
для любого стандартного шаблона библиотеки в пространство имен std, только если объявление зависит от определенного пользователем типа
и специализация соответствует стандартным требованиям библиотеки для исходного шаблона и явно не
запрещено.
Возможно, проще всего было бы унаследовать (и больше ничего не делать) std
введите вместо:
struct hash_t : std::array< unsigned char, 32 >{};
Других решений пока нет …