diff --git a/doc/api.md b/doc/api.md index e86f0b062983..80296ea4e479 100644 --- a/doc/api.md +++ b/doc/api.md @@ -413,11 +413,11 @@ locale: that take `std::locale` as a parameter. The locale type is a template parameter to avoid the expensive `` include. -::: format(detail::locale_ref, format_string, T&&...) +::: format(const Locale&, format_string, T&&...) -::: format_to(OutputIt, detail::locale_ref, format_string, T&&...) +::: format_to(OutputIt, const Locale&, format_string, T&&...) -::: formatted_size(detail::locale_ref, format_string, T&&...) +::: formatted_size(const Locale&, format_string, T&&...) ### Legacy Compile-Time Checks diff --git a/include/fmt/base.h b/include/fmt/base.h index a6948d40b462..e5773c879bed 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -2276,9 +2276,7 @@ struct locale_ref { public: constexpr locale_ref() : locale_(nullptr) {} - - template - locale_ref(const Locale& loc); + template locale_ref(const Locale& loc); inline explicit operator bool() const noexcept { return locale_ != nullptr; } #endif // FMT_USE_LOCALE diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 14c65a0910df..a5b79dbe49b5 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -84,7 +84,7 @@ using std::locale; using std::numpunct; using std::use_facet; -template > +template locale_ref::locale_ref(const Locale& loc) : locale_(&loc) { static_assert(std::is_same::value, ""); } diff --git a/include/fmt/format.h b/include/fmt/format.h index c9a6054d1957..143ef4002bef 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1839,7 +1839,9 @@ template class digit_grouping { } public: - explicit digit_grouping(locale_ref loc, bool localized = true) { + template ::value)> + explicit digit_grouping(Locale loc, bool localized = true) { if (!localized) return; auto sep = thousands_sep(loc); grouping_ = sep.grouping; @@ -3639,6 +3641,12 @@ FMT_CONSTEXPR auto native_formatter::format( return write(ctx.out(), val, specs, ctx.locale()); } +// DEPRECATED! https://github.com/fmtlib/fmt/issues/4292. +template +struct is_locale : std::false_type {}; +template +struct is_locale> : std::true_type {}; + // DEPRECATED! template struct vformat_args { using type = basic_format_args>; @@ -4120,41 +4128,46 @@ FMT_API void format_system_error(detail::buffer& out, int error_code, // Can be used to report errors from destructors. FMT_API void report_system_error(int error_code, const char* message) noexcept; -inline auto vformat(detail::locale_ref loc, string_view fmt, format_args args) +template ::value)> +inline auto vformat(const Locale& loc, string_view fmt, format_args args) -> std::string { auto buf = memory_buffer(); - detail::vformat_to(buf, fmt, args, loc); + detail::vformat_to(buf, fmt, args, detail::locale_ref(loc)); return {buf.data(), buf.size()}; } -template -FMT_INLINE auto format(detail::locale_ref loc, format_string fmt, - T&&... args) -> std::string { +template ::value)> +FMT_INLINE auto format(const Locale& loc, format_string fmt, T&&... args) + -> std::string { return vformat(loc, fmt.str, vargs{{args...}}); } -template ::value)> -auto vformat_to(OutputIt out, detail::locale_ref loc, string_view fmt, - format_args args) -> OutputIt { +auto vformat_to(OutputIt out, Locale loc, string_view fmt, format_args args) + -> OutputIt { auto&& buf = detail::get_buffer(out); - detail::vformat_to(buf, fmt, args, loc); + detail::vformat_to(buf, fmt, args, detail::locale_ref(loc)); return detail::get_iterator(buf, out); } -template ::value)> -FMT_INLINE auto format_to(OutputIt out, detail::locale_ref loc, - format_string fmt, T&&... args) -> OutputIt { +template ::value&& + detail::is_locale::value)> +FMT_INLINE auto format_to(OutputIt out, Locale loc, format_string fmt, + T&&... args) -> OutputIt { return fmt::vformat_to(out, loc, fmt.str, vargs{{args...}}); } -template -FMT_NODISCARD FMT_INLINE auto formatted_size(detail::locale_ref loc, +template ::value)> +FMT_NODISCARD FMT_INLINE auto formatted_size(Locale loc, format_string fmt, T&&... args) -> size_t { auto buf = detail::counting_buffer<>(); - detail::vformat_to(buf, fmt.str, vargs{{args...}}, loc); + detail::vformat_to(buf, fmt.str, vargs{{args...}}, + detail::locale_ref(loc)); return buf.count(); } diff --git a/include/fmt/xchar.h b/include/fmt/xchar.h index 4cbda5421130..9f7f889d64d5 100644 --- a/include/fmt/xchar.h +++ b/include/fmt/xchar.h @@ -191,9 +191,11 @@ auto format(const S& fmt, T&&... args) -> std::basic_string { fmt::make_format_args>(args...)); } -template , - FMT_ENABLE_IF(detail::is_exotic_char::value)> -inline auto vformat(detail::locale_ref loc, const S& fmt, +template , + FMT_ENABLE_IF(detail::is_locale::value&& + detail::is_exotic_char::value)> +inline auto vformat(const Locale& loc, const S& fmt, typename detail::vformat_args::type args) -> std::basic_string { auto buf = basic_memory_buffer(); @@ -202,10 +204,11 @@ inline auto vformat(detail::locale_ref loc, const S& fmt, return {buf.data(), buf.size()}; } -template , - FMT_ENABLE_IF(detail::is_exotic_char::value)> -inline auto format(detail::locale_ref loc, const S& fmt, T&&... args) + FMT_ENABLE_IF(detail::is_locale::value&& + detail::is_exotic_char::value)> +inline auto format(const Locale& loc, const S& fmt, T&&... args) -> std::basic_string { return vformat(loc, detail::to_string_view(fmt), fmt::make_format_args>(args...)); @@ -232,11 +235,12 @@ inline auto format_to(OutputIt out, const S& fmt, T&&... args) -> OutputIt { fmt::make_format_args>(args...)); } -template , FMT_ENABLE_IF(detail::is_output_iterator::value&& - detail::is_exotic_char::value)> -inline auto vformat_to(OutputIt out, detail::locale_ref loc, const S& fmt, + detail::is_locale::value&& + detail::is_exotic_char::value)> +inline auto vformat_to(OutputIt out, const Locale& loc, const S& fmt, typename detail::vformat_args::type args) -> OutputIt { auto&& buf = detail::get_buffer(out); @@ -244,11 +248,12 @@ inline auto vformat_to(OutputIt out, detail::locale_ref loc, const S& fmt, return detail::get_iterator(buf, out); } -template , bool enable = detail::is_output_iterator::value && + detail::is_locale::value && detail::is_exotic_char::value> -inline auto format_to(OutputIt out, detail::locale_ref loc, const S& fmt, +inline auto format_to(OutputIt out, const Locale& loc, const S& fmt, T&&... args) -> typename std::enable_if::type { return vformat_to(out, loc, detail::to_string_view(fmt),