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