Implement templated operator<< as non-member functions only for MSVC

This commit is contained in:
effzeh 2017-05-06 15:12:28 +02:00
parent 7458bb7fe0
commit 47f412bf8b

View File

@ -2111,7 +2111,7 @@ class FormatterBase {
template <typename Char> template <typename Char>
void write(BasicWriter<Char> &w, const Char *start, const Char *end) { void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
if (start != end) if (start != end)
w << BasicStringRef<Char>(start, internal::to_unsigned(end - start)); w.append_str(BasicStringRef<Char>(start, internal::to_unsigned(end - start)));
} }
}; };
} // namespace internal } // namespace internal
@ -2852,11 +2852,54 @@ class BasicWriter : public BasicWriterBase {
return *this; 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 <typename Int, typename Spec, typename FillChar>
BasicWriter &operator<<(const IntFormatSpec<Int, Spec, FillChar> &value) {
append_int(value);
return *this;
}
template <typename Elem>
BasicWriter &operator<<(const StrFormatSpec<Elem> &value) {
append_str(value);
return *this;
}
template <typename Elem>
BasicWriter &operator<<(const fmt::BasicStringRef<Elem> &s) {
append_str(s);
return *this;
}
template <typename Elem, typename Traits, typename Alloc>
BasicWriter &operator<<(const std::basic_string<Elem, Traits, Alloc> &value) {
append_str(fmt::BasicStringRef<Elem>(value));
return *this;
}
#endif
void clear() FMT_NOEXCEPT { buffer_.clear(); } void clear() FMT_NOEXCEPT { buffer_.clear(); }
Buffer<Char> &buffer() FMT_NOEXCEPT { return buffer_; } Buffer<Char> &buffer() FMT_NOEXCEPT { return buffer_; }
}; };
#ifdef _MSC_VER
template <typename Char, typename Int, typename Spec, typename FillChar> template <typename Char, typename Int, typename Spec, typename FillChar>
inline BasicWriter<Char> &operator<<( inline BasicWriter<Char> &operator<<(
BasicWriter<Char> &w, const IntFormatSpec<Int, Spec, FillChar> &value) { BasicWriter<Char> &w, const IntFormatSpec<Int, Spec, FillChar> &value) {
@ -2884,6 +2927,7 @@ inline BasicWriter<Char> &operator<<(
w.append_str(fmt::BasicStringRef<Elem>(value)); w.append_str(fmt::BasicStringRef<Elem>(value));
return w; return w;
} }
#endif
#if FMT_USE_OSTREAM_RVALUE #if FMT_USE_OSTREAM_RVALUE
// http://cplusplus.github.io/LWG/lwg-active.html#1203 // http://cplusplus.github.io/LWG/lwg-active.html#1203