Use type_identity to block unnecessary template argument deduction (thanks Tim Song)

This commit is contained in:
Victor Zverovich 2020-01-15 08:09:48 -08:00
parent 4bbe57cebf
commit c8dd9cc99d
7 changed files with 65 additions and 46 deletions

View File

@ -491,10 +491,8 @@ void vformat_to(basic_memory_buffer<Char>& buf, const text_style& ts,
internal::make_background_color<Char>(ts.get_background()); internal::make_background_color<Char>(ts.get_background());
buf.append(background.begin(), background.end()); buf.append(background.begin(), background.end());
} }
vformat_to(buf, format_str, args); internal::vformat_to(buf, format_str, args);
if (has_style) { if (has_style) internal::reset_color<Char>(buf);
internal::reset_color<Char>(buf);
}
} }
} // namespace internal } // namespace internal

View File

@ -9,6 +9,7 @@
#define FMT_COMPILE_H_ #define FMT_COMPILE_H_
#include <vector> #include <vector>
#include "format.h" #include "format.h"
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
@ -549,7 +550,7 @@ std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
using range = buffer_range<Char>; using range = buffer_range<Char>;
using context = buffer_context<Char>; using context = buffer_context<Char>;
internal::cf::vformat_to<context>(range(buffer), cf, internal::cf::vformat_to<context>(range(buffer), cf,
{make_format_args<context>(args...)}); make_format_args<context>(args...));
return to_string(buffer); return to_string(buffer);
} }
@ -561,8 +562,8 @@ OutputIt format_to(OutputIt out, const CompiledFormat& cf,
using char_type = typename CompiledFormat::char_type; using char_type = typename CompiledFormat::char_type;
using range = internal::output_range<OutputIt, char_type>; using range = internal::output_range<OutputIt, char_type>;
using context = format_context_t<OutputIt, char_type>; using context = format_context_t<OutputIt, char_type>;
return internal::cf::vformat_to<context>( return internal::cf::vformat_to<context>(range(out), cf,
range(out), cf, {make_format_args<context>(args...)}); make_format_args<context>(args...));
} }
template <typename OutputIt, typename CompiledFormat, typename... Args, template <typename OutputIt, typename CompiledFormat, typename... Args,

View File

@ -217,7 +217,7 @@
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
// Implementations of enable_if_t and other metafunctions for pre-C++14 systems. // Implementations of enable_if_t and other metafunctions for older systems.
template <bool B, class T = void> template <bool B, class T = void>
using enable_if_t = typename std::enable_if<B, T>::type; using enable_if_t = typename std::enable_if<B, T>::type;
template <bool B, class T, class F> template <bool B, class T, class F>
@ -229,6 +229,8 @@ template <typename T>
using remove_const_t = typename std::remove_const<T>::type; using remove_const_t = typename std::remove_const<T>::type;
template <typename T> template <typename T>
using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type; using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;
template <typename T> struct type_identity { using type = T; };
template <typename T> using type_identity_t = typename type_identity<T>::type;
struct monostate {}; struct monostate {};
@ -1220,7 +1222,13 @@ using wformat_context = buffer_context<wchar_t>;
such as `~fmt::vformat`. such as `~fmt::vformat`.
\endrst \endrst
*/ */
template <typename Context, typename... Args> class format_arg_store { template <typename Context, typename... Args>
class format_arg_store
#if FMT_GCC_VERSION < 409
// Workaround a GCC template argument substitution bug.
: public basic_format_args<Context>
#endif
{
private: private:
static const size_t num_args = sizeof...(Args); static const size_t num_args = sizeof...(Args);
static const bool is_packed = num_args < internal::max_packed_args; static const bool is_packed = num_args < internal::max_packed_args;
@ -1239,7 +1247,12 @@ template <typename Context, typename... Args> class format_arg_store {
: internal::is_unpacked_bit | num_args; : internal::is_unpacked_bit | num_args;
format_arg_store(const Args&... args) format_arg_store(const Args&... args)
: data_{internal::make_arg<is_packed, Context>(args)...} {} :
#if FMT_GCC_VERSION < 409
basic_format_args<Context>(*this),
#endif
data_{internal::make_arg<is_packed, Context>(args)...} {
}
}; };
/** /**
@ -1426,9 +1439,10 @@ template <typename... Args, typename S, typename Char = char_t<S>>
inline format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> inline format_arg_store<buffer_context<Char>, remove_reference_t<Args>...>
make_args_checked(const S& format_str, make_args_checked(const S& format_str,
const remove_reference_t<Args>&... args) { const remove_reference_t<Args>&... args) {
static_assert(all_true<(!std::is_base_of<view, remove_reference_t<Args>>::value || static_assert(
!std::is_reference<Args>::value)...>::value, all_true<(!std::is_base_of<view, remove_reference_t<Args>>::value ||
"passing views as lvalues is disallowed"); !std::is_reference<Args>::value)...>::value,
"passing views as lvalues is disallowed");
check_format_string<remove_const_t<remove_reference_t<Args>>...>(format_str); check_format_string<remove_const_t<remove_reference_t<Args>>...>(format_str);
return {args...}; return {args...};
} }
@ -1440,7 +1454,7 @@ std::basic_string<Char> vformat(basic_string_view<Char> format_str,
template <typename Char> template <typename Char>
typename buffer_context<Char>::iterator vformat_to( typename buffer_context<Char>::iterator vformat_to(
buffer<Char>& buf, basic_string_view<Char> format_str, buffer<Char>& buf, basic_string_view<Char> format_str,
basic_format_args<buffer_context<Char>> args); basic_format_args<buffer_context<type_identity_t<Char>>> args);
FMT_API void vprint_mojibake(std::FILE*, string_view, format_args); FMT_API void vprint_mojibake(std::FILE*, string_view, format_args);
} // namespace internal } // namespace internal

View File

@ -8,8 +8,6 @@
#ifndef FMT_FORMAT_INL_H_ #ifndef FMT_FORMAT_INL_H_
#define FMT_FORMAT_INL_H_ #define FMT_FORMAT_INL_H_
#include "format.h"
#include <cassert> #include <cassert>
#include <cctype> #include <cctype>
#include <climits> #include <climits>
@ -17,6 +15,8 @@
#include <cstdarg> #include <cstdarg>
#include <cstring> // for std::memmove #include <cstring> // for std::memmove
#include <cwchar> #include <cwchar>
#include "format.h"
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
# include <locale> # include <locale>
#endif #endif
@ -1380,7 +1380,8 @@ FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
FMT_FUNC void internal::vprint_mojibake(std::FILE* f, string_view format_str, FMT_FUNC void internal::vprint_mojibake(std::FILE* f, string_view format_str,
format_args args) { format_args args) {
memory_buffer buffer; memory_buffer buffer;
vformat_to(buffer, format_str, basic_format_args<buffer_context<char>>(args)); internal::vformat_to(buffer, format_str,
basic_format_args<buffer_context<char>>(args));
fwrite_fully(buffer.data(), 1, buffer.size(), f); fwrite_fully(buffer.data(), 1, buffer.size(), f);
} }
#endif #endif

View File

@ -33,8 +33,6 @@
#ifndef FMT_FORMAT_H_ #ifndef FMT_FORMAT_H_
#define FMT_FORMAT_H_ #define FMT_FORMAT_H_
#include "core.h"
#include <algorithm> #include <algorithm>
#include <cerrno> #include <cerrno>
#include <cmath> #include <cmath>
@ -43,6 +41,8 @@
#include <memory> #include <memory>
#include <stdexcept> #include <stdexcept>
#include "core.h"
#ifdef __clang__ #ifdef __clang__
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) # define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
#else #else
@ -3228,7 +3228,7 @@ std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE>& buf) {
template <typename Char> template <typename Char>
typename buffer_context<Char>::iterator internal::vformat_to( typename buffer_context<Char>::iterator internal::vformat_to(
internal::buffer<Char>& buf, basic_string_view<Char> format_str, internal::buffer<Char>& buf, basic_string_view<Char> format_str,
basic_format_args<buffer_context<Char>> args) { basic_format_args<buffer_context<type_identity_t<Char>>> args) {
using range = buffer_range<Char>; using range = buffer_range<Char>;
return vformat_to<arg_formatter<range>>(buf, to_string_view(format_str), return vformat_to<arg_formatter<range>>(buf, to_string_view(format_str),
args); args);
@ -3238,7 +3238,7 @@ template <typename S, typename Char = char_t<S>,
FMT_ENABLE_IF(internal::is_string<S>::value)> FMT_ENABLE_IF(internal::is_string<S>::value)>
inline typename buffer_context<Char>::iterator vformat_to( inline typename buffer_context<Char>::iterator vformat_to(
internal::buffer<Char>& buf, const S& format_str, internal::buffer<Char>& buf, const S& format_str,
basic_format_args<buffer_context<Char>> args) { basic_format_args<buffer_context<type_identity_t<Char>>> args) {
return internal::vformat_to(buf, to_string_view(format_str), args); return internal::vformat_to(buf, to_string_view(format_str), args);
} }
@ -3262,8 +3262,9 @@ template <typename S, typename OutputIt, typename... Args,
FMT_ENABLE_IF( FMT_ENABLE_IF(
internal::is_output_iterator<OutputIt>::value && internal::is_output_iterator<OutputIt>::value &&
!internal::is_contiguous_back_insert_iterator<OutputIt>::value)> !internal::is_contiguous_back_insert_iterator<OutputIt>::value)>
inline OutputIt vformat_to(OutputIt out, const S& format_str, inline OutputIt vformat_to(
format_args_t<OutputIt, char_t<S>> args) { OutputIt out, const S& format_str,
format_args_t<type_identity_t<OutputIt>, char_t<S>> args) {
using range = internal::output_range<OutputIt, char_t<S>>; using range = internal::output_range<OutputIt, char_t<S>>;
return vformat_to<arg_formatter<range>>(range(out), return vformat_to<arg_formatter<range>>(range(out),
to_string_view(format_str), args); to_string_view(format_str), args);
@ -3289,7 +3290,7 @@ inline OutputIt format_to(OutputIt out, const S& format_str, Args&&... args) {
internal::check_format_string<Args...>(format_str); internal::check_format_string<Args...>(format_str);
using context = format_context_t<OutputIt, char_t<S>>; using context = format_context_t<OutputIt, char_t<S>>;
return vformat_to(out, to_string_view(format_str), return vformat_to(out, to_string_view(format_str),
{make_format_args<context>(args...)}); make_format_args<context>(args...));
} }
template <typename OutputIt> struct format_to_n_result { template <typename OutputIt> struct format_to_n_result {
@ -3317,7 +3318,7 @@ template <typename OutputIt, typename Char, typename... Args,
FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value)> FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value)>
inline format_to_n_result<OutputIt> vformat_to_n( inline format_to_n_result<OutputIt> vformat_to_n(
OutputIt out, std::size_t n, basic_string_view<Char> format_str, OutputIt out, std::size_t n, basic_string_view<Char> format_str,
format_to_n_args<OutputIt, Char> args) { format_to_n_args<type_identity_t<OutputIt>, type_identity_t<Char>> args) {
auto it = vformat_to(internal::truncating_iterator<OutputIt>(out, n), auto it = vformat_to(internal::truncating_iterator<OutputIt>(out, n),
format_str, args); format_str, args);
return {it.base(), it.count()}; return {it.base(), it.count()};
@ -3339,7 +3340,7 @@ inline format_to_n_result<OutputIt> format_to_n(OutputIt out, std::size_t n,
internal::check_format_string<Args...>(format_str); internal::check_format_string<Args...>(format_str);
using context = format_to_n_context<OutputIt, char_t<S>>; using context = format_to_n_context<OutputIt, char_t<S>>;
return vformat_to_n(out, n, to_string_view(format_str), return vformat_to_n(out, n, to_string_view(format_str),
{make_format_args<context>(args...)}); make_format_args<context>(args...));
} }
template <typename Char> template <typename Char>

View File

@ -597,7 +597,8 @@ inline format_arg_store<wprintf_context, Args...> make_wprintf_args(
template <typename S, typename Char = char_t<S>> template <typename S, typename Char = char_t<S>>
inline std::basic_string<Char> vsprintf( inline std::basic_string<Char> vsprintf(
const S& format, basic_format_args<basic_printf_context_t<Char>> args) { const S& format,
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
basic_memory_buffer<Char> buffer; basic_memory_buffer<Char> buffer;
printf(buffer, to_string_view(format), args); printf(buffer, to_string_view(format), args);
return to_string(buffer); return to_string(buffer);
@ -616,12 +617,13 @@ template <typename S, typename... Args,
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>> typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
inline std::basic_string<Char> sprintf(const S& format, const Args&... args) { inline std::basic_string<Char> sprintf(const S& format, const Args&... args) {
using context = basic_printf_context_t<Char>; using context = basic_printf_context_t<Char>;
return vsprintf(to_string_view(format), {make_format_args<context>(args...)}); return vsprintf(to_string_view(format), make_format_args<context>(args...));
} }
template <typename S, typename Char = char_t<S>> template <typename S, typename Char = char_t<S>>
inline int vfprintf(std::FILE* f, const S& format, inline int vfprintf(
basic_format_args<basic_printf_context_t<Char>> args) { std::FILE* f, const S& format,
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
basic_memory_buffer<Char> buffer; basic_memory_buffer<Char> buffer;
printf(buffer, to_string_view(format), args); printf(buffer, to_string_view(format), args);
std::size_t size = buffer.size(); std::size_t size = buffer.size();
@ -644,12 +646,13 @@ template <typename S, typename... Args,
inline int fprintf(std::FILE* f, const S& format, const Args&... args) { inline int fprintf(std::FILE* f, const S& format, const Args&... args) {
using context = basic_printf_context_t<Char>; using context = basic_printf_context_t<Char>;
return vfprintf(f, to_string_view(format), return vfprintf(f, to_string_view(format),
{make_format_args<context>(args...)}); make_format_args<context>(args...));
} }
template <typename S, typename Char = char_t<S>> template <typename S, typename Char = char_t<S>>
inline int vprintf(const S& format, inline int vprintf(
basic_format_args<basic_printf_context_t<Char>> args) { const S& format,
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
return vfprintf(stdout, to_string_view(format), args); return vfprintf(stdout, to_string_view(format), args);
} }
@ -667,12 +670,13 @@ template <typename S, typename... Args,
inline int printf(const S& format_str, const Args&... args) { inline int printf(const S& format_str, const Args&... args) {
using context = basic_printf_context_t<char_t<S>>; using context = basic_printf_context_t<char_t<S>>;
return vprintf(to_string_view(format_str), return vprintf(to_string_view(format_str),
{make_format_args<context>(args...)}); make_format_args<context>(args...));
} }
template <typename S, typename Char = char_t<S>> template <typename S, typename Char = char_t<S>>
inline int vfprintf(std::basic_ostream<Char>& os, const S& format, inline int vfprintf(
basic_format_args<basic_printf_context_t<Char>> args) { std::basic_ostream<Char>& os, const S& format,
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
basic_memory_buffer<Char> buffer; basic_memory_buffer<Char> buffer;
printf(buffer, to_string_view(format), args); printf(buffer, to_string_view(format), args);
internal::write(os, buffer); internal::write(os, buffer);
@ -683,9 +687,9 @@ inline int vfprintf(std::basic_ostream<Char>& os, const S& format,
template <typename ArgFormatter, typename Char, template <typename ArgFormatter, typename Char,
typename Context = typename Context =
basic_printf_context<typename ArgFormatter::iterator, Char>> basic_printf_context<typename ArgFormatter::iterator, Char>>
typename ArgFormatter::iterator vprintf(internal::buffer<Char>& out, typename ArgFormatter::iterator vprintf(
basic_string_view<Char> format_str, internal::buffer<Char>& out, basic_string_view<Char> format_str,
basic_format_args<Context> args) { basic_format_args<type_identity_t<Context>> args) {
typename ArgFormatter::iterator iter(out); typename ArgFormatter::iterator iter(out);
Context(iter, format_str, args).template format<ArgFormatter>(); Context(iter, format_str, args).template format<ArgFormatter>();
return iter; return iter;
@ -705,7 +709,7 @@ inline int fprintf(std::basic_ostream<Char>& os, const S& format_str,
const Args&... args) { const Args&... args) {
using context = basic_printf_context_t<Char>; using context = basic_printf_context_t<Char>;
return vfprintf(os, to_string_view(format_str), return vfprintf(os, to_string_view(format_str),
{make_format_args<context>(args...)}); make_format_args<context>(args...));
} }
FMT_END_NAMESPACE FMT_END_NAMESPACE

View File

@ -83,9 +83,9 @@ namespace std {
Out format_to(Out out, wstring_view fmt, const Args&... args); Out format_to(Out out, wstring_view fmt, const Args&... args);
template<class Out> template<class Out>
Out vformat_to(Out out, string_view fmt, format_args_t<Out, char> args); Out vformat_to(Out out, string_view fmt, format_args_t<fmt::type_identity_t<Out>, char> args);
template<class Out> template<class Out>
Out vformat_to(Out out, wstring_view fmt, format_args_t<Out, wchar_t> args); Out vformat_to(Out out, wstring_view fmt, format_args_t<fmt::type_identity_t<Out>, wchar_t> args);
template<class Out> template<class Out>
struct format_to_n_result { struct format_to_n_result {
@ -730,17 +730,17 @@ wstring vformat(wstring_view fmt, wformat_args args);
template<class Out, class... Args> template<class Out, class... Args>
Out format_to(Out out, string_view fmt, const Args&... args) { Out format_to(Out out, string_view fmt, const Args&... args) {
using context = basic_format_context<Out, decltype(fmt)::value_type>; using context = basic_format_context<Out, decltype(fmt)::value_type>;
return vformat_to(out, fmt, {make_format_args<context>(args...)}); return vformat_to(out, fmt, make_format_args<context>(args...));
} }
template<class Out, class... Args> template<class Out, class... Args>
Out format_to(Out out, wstring_view fmt, const Args&... args) { Out format_to(Out out, wstring_view fmt, const Args&... args) {
using context = basic_format_context<Out, decltype(fmt)::value_type>; using context = basic_format_context<Out, decltype(fmt)::value_type>;
return vformat_to(out, fmt, {make_format_args<context>(args...)}); return vformat_to(out, fmt, make_format_args<context>(args...));
} }
template<class Out> template<class Out>
Out vformat_to(Out out, string_view fmt, format_args_t<Out, char> args) { Out vformat_to(Out out, string_view fmt, format_args_t<fmt::type_identity_t<Out>, char> args) {
using range = fmt::internal::output_range<Out, char>; using range = fmt::internal::output_range<Out, char>;
detail::format_handler<detail::arg_formatter<range>, char, basic_format_context<Out, char>> detail::format_handler<detail::arg_formatter<range>, char, basic_format_context<Out, char>>
h(range(out), fmt, args, {}); h(range(out), fmt, args, {});
@ -749,7 +749,7 @@ template<class Out>
} }
template<class Out> template<class Out>
Out vformat_to(Out out, wstring_view fmt, format_args_t<Out, wchar_t> args); Out vformat_to(Out out, wstring_view fmt, format_args_t<fmt::type_identity_t<Out>, wchar_t> args);
template<class Out, class... Args> template<class Out, class... Args>
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,