Commit 4f164097 authored by Victor Zverovich's avatar Victor Zverovich

Merge format overloads using SFINAE

parent 2a4e9488
...@@ -711,7 +711,7 @@ struct result_of<F(Args...)> { ...@@ -711,7 +711,7 @@ struct result_of<F(Args...)> {
typedef typename std::result_of< typedef typename std::result_of<
typename std::remove_reference<F>::type(Args...)>::type type; typename std::remove_reference<F>::type(Args...)>::type type;
}; };
} } // namespace internal
// A formatting argument. It is a trivially copyable/constructible type to // A formatting argument. It is a trivially copyable/constructible type to
// allow storage in basic_memory_buffer. // allow storage in basic_memory_buffer.
...@@ -1292,6 +1292,44 @@ typename std::enable_if< ...@@ -1292,6 +1292,44 @@ typename std::enable_if<
std::string vformat(string_view format_str, format_args args); std::string vformat(string_view format_str, format_args args);
std::wstring vformat(wstring_view format_str, wformat_args args); std::wstring vformat(wstring_view format_str, wformat_args args);
namespace internal {
// If S is a format string type, format_string_traints<S>::char_type gives its
// character type.
template <typename S>
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 <typename Char>
struct format_string_traits_base { typedef Char char_type; };
template <typename Char>
struct format_string_traits<const Char *>: format_string_traits_base<Char> {};
template <typename Char>
struct format_string_traits<Char *>: format_string_traits_base<Char> {};
template <typename Char>
struct format_string_traits<std::basic_string<Char>>:
format_string_traits_base<Char> {};
template <typename Char>
struct format_string_traits<basic_string_view<Char>>:
format_string_traits_base<Char> {};
template <typename S>
struct is_format_string:
std::integral_constant<
bool, std::is_constructible<format_string_traits<S>>::value> {};
template <typename... Args, typename S>
typename std::enable_if<is_format_string<S>::value>::type
check_format_string(S) {}
} // namespace internal
/** /**
\rst \rst
Formats arguments and returns the result as a string. Formats arguments and returns the result as a string.
...@@ -1302,17 +1340,17 @@ std::wstring vformat(wstring_view format_str, wformat_args args); ...@@ -1302,17 +1340,17 @@ std::wstring vformat(wstring_view format_str, wformat_args args);
std::string message = fmt::format("The answer is {}", 42); std::string message = fmt::format("The answer is {}", 42);
\endrst \endrst
*/ */
template <typename... Args> template <typename String, typename... Args>
inline std::string format(string_view format_str, const Args & ... args) { inline std::basic_string<
typename internal::format_string_traits<String>::char_type>
format(String format_str, const Args & ... args) {
typedef typename internal::format_string_traits<String>::char_type char_type;
internal::check_format_string<Args...>(format_str);
// This should be just // This should be just
// return vformat(format_str, make_format_args(args...)); // return vformat(format_str, make_format_args(args...));
// but gcc has trouble optimizing the latter, so break it down. // but gcc has trouble optimizing the latter, so break it down.
format_arg_store<format_context, Args...> as{args...}; typedef typename buffer_context<char_type>::type context_type;
return vformat(format_str, as); format_arg_store<context_type, Args...> as{args...};
}
template <typename... Args>
inline std::wstring format(wstring_view format_str, const Args & ... args) {
format_arg_store<wformat_context, Args...> as{args...};
return vformat(format_str, as); return vformat(format_str, as);
} }
......
...@@ -1352,7 +1352,7 @@ FMT_CONSTEXPR unsigned basic_parse_context<Char, ErrorHandler>::next_arg_id() { ...@@ -1352,7 +1352,7 @@ FMT_CONSTEXPR unsigned basic_parse_context<Char, ErrorHandler>::next_arg_id() {
return 0; return 0;
} }
struct format_string {}; struct compile_string {};
namespace internal { namespace internal {
...@@ -1646,8 +1646,8 @@ class arg_formatter_base { ...@@ -1646,8 +1646,8 @@ class arg_formatter_base {
}; };
template <typename S> template <typename S>
struct is_format_string: struct is_compile_string:
std::integral_constant<bool, std::is_base_of<format_string, S>::value> {}; std::integral_constant<bool, std::is_base_of<compile_string, S>::value> {};
template <typename Char> template <typename Char>
FMT_CONSTEXPR bool is_name_start(Char c) { FMT_CONSTEXPR bool is_name_start(Char c) {
...@@ -2317,7 +2317,8 @@ FMT_CONSTEXPR bool check_format_string( ...@@ -2317,7 +2317,8 @@ FMT_CONSTEXPR bool check_format_string(
} }
template <typename... Args, typename String> template <typename... Args, typename String>
void check_format_string(String format_str) { typename std::enable_if<is_compile_string<String>::value>::type
check_format_string(String format_str) {
FMT_CONSTEXPR_DECL bool invalid_format = FMT_CONSTEXPR_DECL bool invalid_format =
internal::check_format_string<char, internal::error_handler, Args...>( internal::check_format_string<char, internal::error_handler, Args...>(
string_view(format_str.data(), format_str.size())); string_view(format_str.data(), format_str.size()));
...@@ -3678,14 +3679,14 @@ inline std::wstring vformat(wstring_view format_str, wformat_args args) { ...@@ -3678,14 +3679,14 @@ inline std::wstring vformat(wstring_view format_str, wformat_args args) {
template <typename String, typename... Args> template <typename String, typename... Args>
inline typename std::enable_if< inline typename std::enable_if<
internal::is_format_string<String>::value, std::string>::type internal::is_compile_string<String>::value, std::string>::type
format(String format_str, const Args & ... args) { format(String format_str, const Args & ... args) {
internal::check_format_string<Args...>(format_str); internal::check_format_string<Args...>(format_str);
return vformat(format_str.data(), make_format_args(args...)); return vformat(format_str.data(), make_format_args(args...));
} }
template <typename String, typename... Args> template <typename String, typename... Args>
inline typename std::enable_if<internal::is_format_string<String>::value>::type inline typename std::enable_if<internal::is_compile_string<String>::value>::type
print(String format_str, const Args & ... args) { print(String format_str, const Args & ... args) {
internal::check_format_string<Args...>(format_str); internal::check_format_string<Args...>(format_str);
return vprint(format_str.data(), make_format_args(args...)); return vprint(format_str.data(), make_format_args(args...));
...@@ -3979,7 +3980,7 @@ FMT_END_NAMESPACE ...@@ -3979,7 +3980,7 @@ FMT_END_NAMESPACE
#define FMT_STRING(s) [] { \ #define FMT_STRING(s) [] { \
typedef typename std::decay<decltype(s)>::type pointer; \ typedef typename std::decay<decltype(s)>::type pointer; \
struct S : fmt::format_string { \ struct S : fmt::compile_string { \
static FMT_CONSTEXPR pointer data() { return s; } \ static FMT_CONSTEXPR pointer data() { return s; } \
static FMT_CONSTEXPR size_t size() { return sizeof(s); } \ static FMT_CONSTEXPR size_t size() { return sizeof(s); } \
}; \ }; \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment