From 4f1640973071a1b3f391690063eb134a1396b7ed Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 22 Jul 2018 07:20:11 -0700 Subject: [PATCH] Merge format overloads using SFINAE --- include/fmt/core.h | 56 +++++++++++++++++++++++++++++++++++++------- include/fmt/format.h | 15 ++++++------ 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/include/fmt/core.h b/include/fmt/core.h index a3581647..cb2274e3 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -711,7 +711,7 @@ struct result_of { typedef typename std::result_of< typename std::remove_reference::type(Args...)>::type type; }; -} +} // namespace internal // A formatting argument. It is a trivially copyable/constructible type to // allow storage in basic_memory_buffer. @@ -1292,6 +1292,44 @@ typename std::enable_if< std::string vformat(string_view format_str, format_args args); std::wstring vformat(wstring_view format_str, wformat_args args); +namespace internal { +// If S is a format string type, format_string_traints::char_type gives its +// character type. +template +struct format_string_traits { + private: + // Use construtbility as a way to detect if format_string_traits is + // specialized because other methods are broken on MSVC2013. + format_string_traits(); +}; + +template +struct format_string_traits_base { typedef Char char_type; }; + +template +struct format_string_traits: format_string_traits_base {}; + +template +struct format_string_traits: format_string_traits_base {}; + +template +struct format_string_traits>: + format_string_traits_base {}; + +template +struct format_string_traits>: + format_string_traits_base {}; + +template +struct is_format_string: + std::integral_constant< + bool, std::is_constructible>::value> {}; + +template +typename std::enable_if::value>::type + check_format_string(S) {} +} // namespace internal + /** \rst Formats arguments and returns the result as a string. @@ -1302,17 +1340,17 @@ std::wstring vformat(wstring_view format_str, wformat_args args); std::string message = fmt::format("The answer is {}", 42); \endrst */ -template -inline std::string format(string_view format_str, const Args & ... args) { +template +inline std::basic_string< + typename internal::format_string_traits::char_type> + format(String format_str, const Args & ... args) { + typedef typename internal::format_string_traits::char_type char_type; + internal::check_format_string(format_str); // This should be just // return vformat(format_str, make_format_args(args...)); // but gcc has trouble optimizing the latter, so break it down. - format_arg_store as{args...}; - return vformat(format_str, as); -} -template -inline std::wstring format(wstring_view format_str, const Args & ... args) { - format_arg_store as{args...}; + typedef typename buffer_context::type context_type; + format_arg_store as{args...}; return vformat(format_str, as); } diff --git a/include/fmt/format.h b/include/fmt/format.h index b80704dc..e522ca4f 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1352,7 +1352,7 @@ FMT_CONSTEXPR unsigned basic_parse_context::next_arg_id() { return 0; } -struct format_string {}; +struct compile_string {}; namespace internal { @@ -1646,8 +1646,8 @@ class arg_formatter_base { }; template -struct is_format_string: - std::integral_constant::value> {}; +struct is_compile_string: + std::integral_constant::value> {}; template FMT_CONSTEXPR bool is_name_start(Char c) { @@ -2317,7 +2317,8 @@ FMT_CONSTEXPR bool check_format_string( } template -void check_format_string(String format_str) { +typename std::enable_if::value>::type + check_format_string(String format_str) { FMT_CONSTEXPR_DECL bool invalid_format = internal::check_format_string( string_view(format_str.data(), format_str.size())); @@ -3678,14 +3679,14 @@ inline std::wstring vformat(wstring_view format_str, wformat_args args) { template inline typename std::enable_if< - internal::is_format_string::value, std::string>::type + internal::is_compile_string::value, std::string>::type format(String format_str, const Args & ... args) { internal::check_format_string(format_str); return vformat(format_str.data(), make_format_args(args...)); } template -inline typename std::enable_if::value>::type +inline typename std::enable_if::value>::type print(String format_str, const Args & ... args) { internal::check_format_string(format_str); return vprint(format_str.data(), make_format_args(args...)); @@ -3979,7 +3980,7 @@ FMT_END_NAMESPACE #define FMT_STRING(s) [] { \ typedef typename std::decay::type pointer; \ - struct S : fmt::format_string { \ + struct S : fmt::compile_string { \ static FMT_CONSTEXPR pointer data() { return s; } \ static FMT_CONSTEXPR size_t size() { return sizeof(s); } \ }; \