diff --git a/include/fmt/color.h b/include/fmt/color.h index df912fe2..1d4ab19a 100644 --- a/include/fmt/color.h +++ b/include/fmt/color.h @@ -269,9 +269,8 @@ inline void reset_color(FILE *stream) FMT_NOEXCEPT { } // namespace internal template < - typename String, - typename Char = typename internal::has_to_string_view::char_type> -void vprint_rgb(rgb fd, const String &format, + typename S, typename Char = typename internal::char_t::type> +void vprint_rgb(rgb fd, const S &format, basic_format_args::type> args) { internal::fputs(internal::make_foreground_color(fd), stdout); vprint(format, args); @@ -279,9 +278,8 @@ void vprint_rgb(rgb fd, const String &format, } template < - typename String, - typename Char = typename internal::has_to_string_view::char_type> -void vprint_rgb(rgb fd, rgb bg, const String &format, + typename S, typename Char = typename internal::char_t::type> +void vprint_rgb(rgb fd, rgb bg, const S &format, basic_format_args::type> args) { internal::fputs(internal::make_foreground_color(fd), stdout); internal::fputs(internal::make_background_color(bg), stdout); @@ -299,7 +297,7 @@ template typename std::enable_if::value>::type print(rgb fd, const String &format_str, const Args & ... args) { internal::check_format_string(format_str); - typedef typename internal::has_to_string_view::char_type char_t; + typedef typename internal::char_t::type char_t; typedef typename buffer_context::type context_t; format_arg_store as{args...}; vprint_rgb(fd, format_str, basic_format_args(as)); @@ -316,7 +314,7 @@ template typename std::enable_if::value>::type print(rgb fd, rgb bg, const String &format_str, const Args & ... args) { internal::check_format_string(format_str); - typedef typename internal::has_to_string_view::char_type char_t; + typedef typename internal::is_string::char_type char_t; typedef typename buffer_context::type context_t; format_arg_store as{args...}; vprint_rgb(fd, bg, format_str, basic_format_args(as)); diff --git a/include/fmt/core.h b/include/fmt/core.h index 1992c694..8180340b 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -426,6 +426,32 @@ class basic_string_view { typedef basic_string_view string_view; typedef basic_string_view wstring_view; +/** + \rst + The function ``to_string_view`` adapts non-intrusively any kind of string or + string-like type if the user provides a (possibly templated) overload of + ``to_string_view`` which takes an instance of the string class + ``StringType`` and returns a ``fmt::basic_string_view``. + The conversion function must live in the very same namespace as + ``StringType`` to be picked up by ADL. Non-templated string types + like f.e. QString must return a ``basic_string_view`` with a fixed matching + char type. + + **Example**:: + + namespace my_ns { + inline string_view to_string_view(const my_string &s) { + return { s.data(), s.length() }; + } + } + + std::string message = fmt::format(my_string("The answer is {}"), 42); + \endrst + */ +template +inline basic_string_view + to_string_view(basic_string_view s) { return s; } + template inline basic_string_view to_string_view(const std::basic_string &s) { return s; } @@ -476,29 +502,21 @@ struct convert_to_int: std::integral_constant< namespace internal { -template -struct get_char_type { - typedef void char_type; -}; - -template -struct get_char_type> { - typedef Char char_type; -}; - +struct dummy_string_view { typedef void char_type; }; +dummy_string_view to_string_view(...); using fmt::v5::to_string_view; -void to_string_view(...); +// Specifies whether S is a string type convertible to fmt::basic_string_view. +template +struct is_string : std::integral_constant()))>::value> {}; template -struct has_to_string_view { - typedef typename get_char_type()))>::char_type char_type; - static const bool value = !std::is_same()))>::value; +struct char_t { + typedef decltype(to_string_view(declval())) result; + typedef typename result::char_type type; }; -template -struct is_string : internal::has_to_string_view {}; - template struct named_arg_base; @@ -708,7 +726,7 @@ inline typename std::enable_if< template inline typename std::enable_if< internal::is_constructible, T>::value && - !internal::has_to_string_view::value, + !internal::is_string::value, init, string_type>>::type make_value(const T &val) { return basic_string_view(val); } @@ -717,7 +735,7 @@ inline typename std::enable_if< !convert_to_int::value && !std::is_same::value && !std::is_convertible>::value && !internal::is_constructible, T>::value && - !internal::has_to_string_view::value, + !internal::is_string::value, // Implicit conversion to std::string is not handled here because it's // unsafe: https://github.com/fmtlib/fmt/issues/729 init>::type @@ -733,13 +751,12 @@ init template FMT_CONSTEXPR11 typename std::enable_if< - internal::has_to_string_view::value, + internal::is_string::value, init, string_type>>::type make_value(const S &val) { // Handle adapted strings. static_assert(std::is_same< - typename C::char_type, - typename internal::has_to_string_view::char_type>::value, + typename C::char_type, typename internal::char_t::type>::value, "mismatch between char-types of context and argument"); return to_string_view(val); } @@ -1264,9 +1281,9 @@ struct wformat_args : basic_format_args { #if FMT_USE_ALIAS_TEMPLATES /** String's character type. */ template -using char_t = typename std::enable_if::value, - typename internal::has_to_string_view::char_type>::type; -#define FMT_CHAR(S) char_t +using char_t = typename std::enable_if::value, + typename internal::char_t::type>::type; +#define FMT_CHAR(S) fmt::char_t template using enable_if_string_t = @@ -1275,8 +1292,7 @@ using enable_if_string_t = #else template struct char_t : std::enable_if< - internal::has_to_string_view::value, - typename internal::has_to_string_view::char_type> {}; + internal::is_string::value, typename internal::char_t::type> {}; #define FMT_CHAR(S) typename char_t::type #define FMT_ENABLE_IF_STRING(S, T) \ @@ -1336,33 +1352,6 @@ std::basic_string vformat( basic_format_args::type> args); } -/** - \rst - The function ``to_string_view`` adapts non-intrusively any kind of string or - string-like type if the user provides a (possibly templated) overload of - ``to_string_view`` which takes an instance of the string class - ``StringType`` and returns a ``fmt::basic_string_view``. - The conversion function must live in the very same namespace as - ``StringType`` to be picked up by ADL. Non-templated string types - like f.e. QString must return a ``basic_string_view`` with a fixed matching - char type. - - **Example**:: - - namespace my_ns { - inline string_view to_string_view(const my_string &s) { - return { s.data(), s.length() }; - } - } - - std::string message = fmt::format(my_string("The answer is {}"), 42); - \endrst - */ -template -inline basic_string_view to_string_view(basic_string_view s) { - return s; -} - /** \rst Returns a named argument to be used in a formatting function. diff --git a/include/fmt/format.h b/include/fmt/format.h index 031436d3..bbe4926c 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -753,7 +753,7 @@ class truncating_iterator_base { typedef void difference_type; typedef void pointer; typedef void reference; - typedef truncating_iterator_base _Unchecked_type; // Mark iterator as checked. + typedef truncating_iterator_base _Unchecked_type; // Mark iterator as checked. OutputIt base() const { return out_; } std::size_t count() const { return count_; } @@ -811,9 +811,7 @@ class truncating_iterator: } truncating_iterator& operator++() { return *this; } - truncating_iterator& operator++(int) { return *this; } - truncating_iterator& operator*() { return *this; } }; @@ -3377,11 +3375,11 @@ inline typename buffer_context::type::iterator vformat_to( } template < - typename String, typename... Args, + typename S, typename... Args, std::size_t SIZE = inline_buffer_size, - typename Char = typename internal::has_to_string_view::char_type> + typename Char = typename internal::char_t::type> inline typename buffer_context::type::iterator format_to( - basic_memory_buffer &buf, const String &format_str, + basic_memory_buffer &buf, const S &format_str, const Args &... args) { internal::check_format_string(format_str); typedef typename buffer_context::type context;