From 47f412bf8b2b6c688ec32a78fbef782853c7a70b Mon Sep 17 00:00:00 2001 From: effzeh Date: Sat, 6 May 2017 15:12:28 +0200 Subject: [PATCH] Implement templated operator<< as non-member functions only for MSVC --- fmt/format.h | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/fmt/format.h b/fmt/format.h index b0f77db1..fc2dcd8f 100644 --- a/fmt/format.h +++ b/fmt/format.h @@ -2111,7 +2111,7 @@ class FormatterBase { template void write(BasicWriter &w, const Char *start, const Char *end) { if (start != end) - w << BasicStringRef(start, internal::to_unsigned(end - start)); + w.append_str(BasicStringRef(start, internal::to_unsigned(end - start))); } }; } // namespace internal @@ -2852,11 +2852,54 @@ class BasicWriter : public BasicWriterBase { return *this; } + // MSVC complains about ambiguous operator<< if these templates are defined as + // member functions and an operator<<(Writer&, const T&) is visible, e.g. + // if ostream.h is included. + // + // MSVC also has a language extension which can convert rvalues to lvalues and + // which allows e.g. + // MemoryWriter() << bin(123); + // to work (calls the non-member function). + // + // If they are defined as non-member functions, GCC in C++98 mode cannot call + // them in cases like the one above. + // In C++11 mode, the overload defined below is used. This is only fast, if + // moving a BasicWriter is fast and this is, e.g., not the case for a + // MemoryWriter which uses its inline buffer. So it seems beneficial to + // implement operator<< as member functions. + +#ifndef _MSC_VER + template + BasicWriter &operator<<(const IntFormatSpec &value) { + append_int(value); + return *this; + } + + template + BasicWriter &operator<<(const StrFormatSpec &value) { + append_str(value); + return *this; + } + + template + BasicWriter &operator<<(const fmt::BasicStringRef &s) { + append_str(s); + return *this; + } + + template + BasicWriter &operator<<(const std::basic_string &value) { + append_str(fmt::BasicStringRef(value)); + return *this; + } +#endif + void clear() FMT_NOEXCEPT { buffer_.clear(); } Buffer &buffer() FMT_NOEXCEPT { return buffer_; } }; +#ifdef _MSC_VER template inline BasicWriter &operator<<( BasicWriter &w, const IntFormatSpec &value) { @@ -2884,6 +2927,7 @@ inline BasicWriter &operator<<( w.append_str(fmt::BasicStringRef(value)); return w; } +#endif #if FMT_USE_OSTREAM_RVALUE // http://cplusplus.github.io/LWG/lwg-active.html#1203