From 7da193fde1a9c1bc925ee980339f4df2e1a66fa7 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 23 Aug 2015 17:27:20 +0300 Subject: [PATCH] Fixed compilation of operator<< into a record ostream, when the operator right hand argument is not directly supported by formatting_ostream. Fixed #11549. --- diff --git a/include/boost/log/sources/record_ostream.hpp b/include/boost/log/sources/record_ostream.hpp index b3c58e2..c1e8059 100644 --- a/include/boost/log/sources/record_ostream.hpp +++ b/include/boost/log/sources/record_ostream.hpp @@ -39,6 +39,18 @@ namespace boost { BOOST_LOG_OPEN_NAMESPACE +template< typename CharT > +class basic_record_ostream; + +namespace aux { + +template< typename StreamT, typename R > +struct enable_if_record_ostream {}; +template< typename CharT, typename R > +struct enable_if_record_ostream< basic_record_ostream< CharT >, R > { typedef R type; }; + +} // namespace aux + /*! * \brief Logging record adapter with a streaming capability * @@ -174,6 +186,55 @@ typedef basic_record_ostream< char > record_ostream; //!< Convenience typ typedef basic_record_ostream< wchar_t > wrecord_ostream; //!< Convenience typedef for wide-character logging #endif +// Implementation note: these operators below should be the least attractive for the compiler +// so that user's overloads are chosen, when present. We use function template partial ordering for this purpose. +// We also don't use perfect forwarding for the right hand argument because in ths case the generic overload +// would be more preferred than the typical one written by users: +// +// record_ostream& operator<< (record_ostream& strm, my_type const& arg); +// +// This is because my_type rvalues require adding const to the type, which counts as a conversion that is not required +// if there is a perfect forwarding overload. +template< typename StreamT, typename T > +inline typename boost::log::aux::enable_if_record_ostream< StreamT, StreamT& >::type +operator<< (StreamT& strm, T const& value) +{ + typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type; + static_cast< formatting_ostream_type& >(strm) << value; + return strm; +} + +template< typename StreamT, typename T > +inline typename boost::log::aux::enable_if_record_ostream< StreamT, StreamT& >::type +operator<< (StreamT& strm, T& value) +{ + typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type; + static_cast< formatting_ostream_type& >(strm) << value; + return strm; +} + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template< typename StreamT, typename T > +inline typename boost::log::aux::enable_if_record_ostream< StreamT, StreamT& >::type +operator<< (StreamT&& strm, T const& value) +{ + typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type; + static_cast< formatting_ostream_type& >(strm) << value; + return strm; +} + +template< typename StreamT, typename T > +inline typename boost::log::aux::enable_if_record_ostream< StreamT, StreamT& >::type +operator<< (StreamT&& strm, T& value) +{ + typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type; + static_cast< formatting_ostream_type& >(strm) << value; + return strm; +} + +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + namespace aux { //! Internal class that provides formatting streams for record pumps diff --git a/include/boost/log/utility/formatting_ostream.hpp b/include/boost/log/utility/formatting_ostream.hpp index 4345206..744acc0 100644 --- a/include/boost/log/utility/formatting_ostream.hpp +++ b/include/boost/log/utility/formatting_ostream.hpp @@ -779,6 +779,13 @@ void basic_formatting_ostream< CharT, TraitsT, AllocatorT >::aligned_write(const // Implementation note: these operators below should be the least attractive for the compiler // so that user's overloads are chosen, when present. We use function template partial ordering for this purpose. +// We also don't use perfect forwarding for the right hand argument because in ths case the generic overload +// would be more preferred than the typical one written by users: +// +// formatting_ostream& operator<< (formatting_ostream& strm, my_type const& arg); +// +// This is because my_type rvalues require adding const to the type, which counts as a conversion that is not required +// if there is a perfect forwarding overload. template< typename StreamT, typename T > inline typename boost::log::aux::enable_if_formatting_ostream< StreamT, StreamT& >::type operator<< (StreamT& strm, T const& value)