Use type_identity to block unnecessary template argument deduction (thanks Tim Song)
This commit is contained in:
parent
4bbe57cebf
commit
c8dd9cc99d
@ -491,10 +491,8 @@ void vformat_to(basic_memory_buffer<Char>& buf, const text_style& ts,
|
||||
internal::make_background_color<Char>(ts.get_background());
|
||||
buf.append(background.begin(), background.end());
|
||||
}
|
||||
vformat_to(buf, format_str, args);
|
||||
if (has_style) {
|
||||
internal::reset_color<Char>(buf);
|
||||
}
|
||||
internal::vformat_to(buf, format_str, args);
|
||||
if (has_style) internal::reset_color<Char>(buf);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define FMT_COMPILE_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "format.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
@ -549,7 +550,7 @@ std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
|
||||
using range = buffer_range<Char>;
|
||||
using context = buffer_context<Char>;
|
||||
internal::cf::vformat_to<context>(range(buffer), cf,
|
||||
{make_format_args<context>(args...)});
|
||||
make_format_args<context>(args...));
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
@ -561,8 +562,8 @@ OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
||||
using char_type = typename CompiledFormat::char_type;
|
||||
using range = internal::output_range<OutputIt, char_type>;
|
||||
using context = format_context_t<OutputIt, char_type>;
|
||||
return internal::cf::vformat_to<context>(
|
||||
range(out), cf, {make_format_args<context>(args...)});
|
||||
return internal::cf::vformat_to<context>(range(out), cf,
|
||||
make_format_args<context>(args...));
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
||||
|
@ -217,7 +217,7 @@
|
||||
|
||||
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>
|
||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
template <bool B, class T, class F>
|
||||
@ -229,6 +229,8 @@ template <typename T>
|
||||
using remove_const_t = typename std::remove_const<T>::type;
|
||||
template <typename T>
|
||||
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 {};
|
||||
|
||||
@ -1220,7 +1222,13 @@ using wformat_context = buffer_context<wchar_t>;
|
||||
such as `~fmt::vformat`.
|
||||
\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:
|
||||
static const size_t num_args = sizeof...(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;
|
||||
|
||||
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>...>
|
||||
make_args_checked(const S& format_str,
|
||||
const remove_reference_t<Args>&... args) {
|
||||
static_assert(all_true<(!std::is_base_of<view, remove_reference_t<Args>>::value ||
|
||||
!std::is_reference<Args>::value)...>::value,
|
||||
"passing views as lvalues is disallowed");
|
||||
static_assert(
|
||||
all_true<(!std::is_base_of<view, remove_reference_t<Args>>::value ||
|
||||
!std::is_reference<Args>::value)...>::value,
|
||||
"passing views as lvalues is disallowed");
|
||||
check_format_string<remove_const_t<remove_reference_t<Args>>...>(format_str);
|
||||
return {args...};
|
||||
}
|
||||
@ -1440,7 +1454,7 @@ std::basic_string<Char> vformat(basic_string_view<Char> format_str,
|
||||
template <typename Char>
|
||||
typename buffer_context<Char>::iterator vformat_to(
|
||||
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);
|
||||
} // namespace internal
|
||||
|
@ -8,8 +8,6 @@
|
||||
#ifndef FMT_FORMAT_INL_H_
|
||||
#define FMT_FORMAT_INL_H_
|
||||
|
||||
#include "format.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <climits>
|
||||
@ -17,6 +15,8 @@
|
||||
#include <cstdarg>
|
||||
#include <cstring> // for std::memmove
|
||||
#include <cwchar>
|
||||
|
||||
#include "format.h"
|
||||
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
|
||||
# include <locale>
|
||||
#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,
|
||||
format_args args) {
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
@ -33,8 +33,6 @@
|
||||
#ifndef FMT_FORMAT_H_
|
||||
#define FMT_FORMAT_H_
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <cmath>
|
||||
@ -43,6 +41,8 @@
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#ifdef __clang__
|
||||
# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
|
||||
#else
|
||||
@ -3228,7 +3228,7 @@ std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE>& buf) {
|
||||
template <typename Char>
|
||||
typename buffer_context<Char>::iterator internal::vformat_to(
|
||||
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>;
|
||||
return vformat_to<arg_formatter<range>>(buf, to_string_view(format_str),
|
||||
args);
|
||||
@ -3238,7 +3238,7 @@ template <typename S, typename Char = char_t<S>,
|
||||
FMT_ENABLE_IF(internal::is_string<S>::value)>
|
||||
inline typename buffer_context<Char>::iterator vformat_to(
|
||||
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);
|
||||
}
|
||||
|
||||
@ -3262,8 +3262,9 @@ template <typename S, typename OutputIt, typename... Args,
|
||||
FMT_ENABLE_IF(
|
||||
internal::is_output_iterator<OutputIt>::value &&
|
||||
!internal::is_contiguous_back_insert_iterator<OutputIt>::value)>
|
||||
inline OutputIt vformat_to(OutputIt out, const S& format_str,
|
||||
format_args_t<OutputIt, char_t<S>> args) {
|
||||
inline OutputIt vformat_to(
|
||||
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>>;
|
||||
return vformat_to<arg_formatter<range>>(range(out),
|
||||
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);
|
||||
using context = format_context_t<OutputIt, char_t<S>>;
|
||||
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 {
|
||||
@ -3317,7 +3318,7 @@ template <typename OutputIt, typename Char, typename... Args,
|
||||
FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value)>
|
||||
inline format_to_n_result<OutputIt> vformat_to_n(
|
||||
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),
|
||||
format_str, args);
|
||||
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);
|
||||
using context = format_to_n_context<OutputIt, char_t<S>>;
|
||||
return vformat_to_n(out, n, to_string_view(format_str),
|
||||
{make_format_args<context>(args...)});
|
||||
make_format_args<context>(args...));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
|
@ -597,7 +597,8 @@ inline format_arg_store<wprintf_context, Args...> make_wprintf_args(
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
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;
|
||||
printf(buffer, to_string_view(format), args);
|
||||
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>>>
|
||||
inline std::basic_string<Char> sprintf(const S& format, const Args&... args) {
|
||||
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>>
|
||||
inline int vfprintf(std::FILE* f, const S& format,
|
||||
basic_format_args<basic_printf_context_t<Char>> args) {
|
||||
inline int vfprintf(
|
||||
std::FILE* f, const S& format,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
printf(buffer, to_string_view(format), args);
|
||||
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) {
|
||||
using context = basic_printf_context_t<Char>;
|
||||
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>>
|
||||
inline int vprintf(const S& format,
|
||||
basic_format_args<basic_printf_context_t<Char>> args) {
|
||||
inline int vprintf(
|
||||
const S& format,
|
||||
basic_format_args<basic_printf_context_t<type_identity_t<Char>>> 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) {
|
||||
using context = basic_printf_context_t<char_t<S>>;
|
||||
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>>
|
||||
inline int vfprintf(std::basic_ostream<Char>& os, const S& format,
|
||||
basic_format_args<basic_printf_context_t<Char>> args) {
|
||||
inline int vfprintf(
|
||||
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;
|
||||
printf(buffer, to_string_view(format), args);
|
||||
internal::write(os, buffer);
|
||||
@ -683,9 +687,9 @@ inline int vfprintf(std::basic_ostream<Char>& os, const S& format,
|
||||
template <typename ArgFormatter, typename Char,
|
||||
typename Context =
|
||||
basic_printf_context<typename ArgFormatter::iterator, Char>>
|
||||
typename ArgFormatter::iterator vprintf(internal::buffer<Char>& out,
|
||||
basic_string_view<Char> format_str,
|
||||
basic_format_args<Context> args) {
|
||||
typename ArgFormatter::iterator vprintf(
|
||||
internal::buffer<Char>& out, basic_string_view<Char> format_str,
|
||||
basic_format_args<type_identity_t<Context>> args) {
|
||||
typename ArgFormatter::iterator iter(out);
|
||||
Context(iter, format_str, args).template format<ArgFormatter>();
|
||||
return iter;
|
||||
@ -705,7 +709,7 @@ inline int fprintf(std::basic_ostream<Char>& os, const S& format_str,
|
||||
const Args&... args) {
|
||||
using context = basic_printf_context_t<Char>;
|
||||
return vfprintf(os, to_string_view(format_str),
|
||||
{make_format_args<context>(args...)});
|
||||
make_format_args<context>(args...));
|
||||
}
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
|
12
test/format
12
test/format
@ -83,9 +83,9 @@ namespace std {
|
||||
Out format_to(Out out, wstring_view fmt, const Args&... args);
|
||||
|
||||
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>
|
||||
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>
|
||||
struct format_to_n_result {
|
||||
@ -730,17 +730,17 @@ wstring vformat(wstring_view fmt, wformat_args args);
|
||||
template<class Out, class... Args>
|
||||
Out format_to(Out out, string_view fmt, const Args&... args) {
|
||||
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>
|
||||
Out format_to(Out out, wstring_view fmt, const Args&... args) {
|
||||
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>
|
||||
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>;
|
||||
detail::format_handler<detail::arg_formatter<range>, char, basic_format_context<Out, char>>
|
||||
h(range(out), fmt, args, {});
|
||||
@ -749,7 +749,7 @@ 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>
|
||||
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
|
||||
|
Loading…
Reference in New Issue
Block a user