Implement templated operator<< as non-member functions only for MSVC
This commit is contained in:
parent
7458bb7fe0
commit
47f412bf8b
46
fmt/format.h
46
fmt/format.h
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user