mirror of
https://github.com/fmtlib/fmt.git
synced 2025-01-19 10:40:08 +00:00
Remove extra level of indirection when building args
This commit is contained in:
parent
9f73e45ca0
commit
545d37a8b0
@ -1099,7 +1099,7 @@ FMT_CONSTEXPR void basic_format_parse_context<Char>::check_dynamic_spec(
|
||||
|
||||
FMT_EXPORT template <typename Context> class basic_format_arg;
|
||||
FMT_EXPORT template <typename Context> class basic_format_args;
|
||||
FMT_EXPORT template <typename Context, typename... Args> class format_arg_store;
|
||||
FMT_EXPORT template <typename, size_t, typename...> class format_arg_store_impl;
|
||||
FMT_EXPORT template <typename Context> class dynamic_format_arg_store;
|
||||
|
||||
// A formatter for objects of type T.
|
||||
@ -1192,33 +1192,6 @@ template <typename Char> struct named_arg_info {
|
||||
int id;
|
||||
};
|
||||
|
||||
template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
|
||||
struct arg_data {
|
||||
// args_[0].named_args points to named_args_ to avoid bloating format_args.
|
||||
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
|
||||
T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)];
|
||||
named_arg_info<Char> named_args_[NUM_NAMED_ARGS];
|
||||
|
||||
template <typename... U>
|
||||
arg_data(const U&... init) : args_{T(named_args_, NUM_NAMED_ARGS), init...} {}
|
||||
arg_data(const arg_data& other) = delete;
|
||||
auto args() const -> const T* { return args_ + 1; }
|
||||
auto named_args() -> named_arg_info<Char>* { return named_args_; }
|
||||
};
|
||||
|
||||
template <typename T, typename Char, size_t NUM_ARGS>
|
||||
struct arg_data<T, Char, NUM_ARGS, 0> {
|
||||
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
|
||||
T args_[NUM_ARGS != 0 ? NUM_ARGS : +1];
|
||||
|
||||
template <typename... U>
|
||||
FMT_CONSTEXPR FMT_INLINE arg_data(const U&... init) : args_{init...} {}
|
||||
FMT_CONSTEXPR FMT_INLINE auto args() const -> const T* { return args_; }
|
||||
FMT_CONSTEXPR FMT_INLINE auto named_args() -> std::nullptr_t {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
inline void init_named_args(named_arg_info<Char>*, int, int) {}
|
||||
|
||||
@ -1638,8 +1611,7 @@ template <typename Context> class basic_format_arg {
|
||||
|
||||
using char_type = typename Context::char_type;
|
||||
|
||||
template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
|
||||
friend struct detail::arg_data;
|
||||
template <typename, size_t, typename...> friend class format_arg_store_impl;
|
||||
|
||||
basic_format_arg(const detail::named_arg_info<char_type>* args, size_t size)
|
||||
: value_(args, size) {}
|
||||
@ -1792,11 +1764,11 @@ template <typename Context> class basic_format_args {
|
||||
Constructs a `basic_format_args` object from `~fmt::format_arg_store`.
|
||||
\endrst
|
||||
*/
|
||||
template <typename... Args>
|
||||
template <size_t N, typename... Args>
|
||||
constexpr FMT_INLINE basic_format_args(
|
||||
const format_arg_store<Context, Args...>& store)
|
||||
: basic_format_args(format_arg_store<Context, Args...>::desc,
|
||||
store.data_.args()) {}
|
||||
const format_arg_store_impl<Context, N, Args...>& store)
|
||||
: basic_format_args(format_arg_store_impl<Context, N, Args...>::desc,
|
||||
store.args()) {}
|
||||
|
||||
/**
|
||||
\rst
|
||||
@ -1926,8 +1898,52 @@ using is_formattable = bool_constant<!std::is_base_of<
|
||||
such as `~fmt::vformat`.
|
||||
\endrst
|
||||
*/
|
||||
template <typename Context, typename... Args>
|
||||
class format_arg_store
|
||||
template <typename Context, size_t NUM_NAMED_ARGS, typename... Args>
|
||||
class format_arg_store_impl
|
||||
#if FMT_GCC_VERSION && 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 <= detail::max_packed_args;
|
||||
|
||||
using char_type = typename Context::char_type;
|
||||
using value_type = conditional_t<is_packed, detail::value<Context>,
|
||||
basic_format_arg<Context>>;
|
||||
|
||||
// args_[0].named_args points to named_args_ to avoid bloating format_args.
|
||||
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
|
||||
value_type args_[1 + (num_args != 0 ? num_args : +1)];
|
||||
detail::named_arg_info<char_type> named_args_[NUM_NAMED_ARGS];
|
||||
|
||||
public:
|
||||
template <typename... T>
|
||||
FMT_CONSTEXPR FMT_INLINE format_arg_store_impl(T&... args)
|
||||
:
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
|
||||
basic_format_args<Context>(*this),
|
||||
#endif
|
||||
args_{value_type(named_args_, NUM_NAMED_ARGS),
|
||||
detail::make_arg<is_packed, Context>(args)...} {
|
||||
detail::init_named_args(named_args_, 0, 0, args...);
|
||||
}
|
||||
|
||||
static constexpr unsigned long long desc =
|
||||
(is_packed ? detail::encode_types<Context, Args...>()
|
||||
: detail::is_unpacked_bit | num_args) |
|
||||
(NUM_NAMED_ARGS != 0
|
||||
? static_cast<unsigned long long>(detail::has_named_args_bit)
|
||||
: 0);
|
||||
|
||||
FMT_CONSTEXPR FMT_INLINE auto args() const -> const value_type* {
|
||||
return args_ + 1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Context, typename... Args>
|
||||
class format_arg_store_impl<Context, 0, Args...>
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
|
||||
// Workaround a GCC template argument substitution bug.
|
||||
: public basic_format_args<Context>
|
||||
@ -1935,38 +1951,37 @@ class format_arg_store
|
||||
{
|
||||
private:
|
||||
static const size_t num_args = sizeof...(Args);
|
||||
static constexpr size_t num_named_args = detail::count_named_args<Args...>();
|
||||
static const bool is_packed = num_args <= detail::max_packed_args;
|
||||
|
||||
using value_type = conditional_t<is_packed, detail::value<Context>,
|
||||
basic_format_arg<Context>>;
|
||||
|
||||
detail::arg_data<value_type, typename Context::char_type, num_args,
|
||||
num_named_args>
|
||||
data_;
|
||||
|
||||
friend class basic_format_args<Context>;
|
||||
|
||||
static constexpr unsigned long long desc =
|
||||
(is_packed ? detail::encode_types<Context, Args...>()
|
||||
: detail::is_unpacked_bit | num_args) |
|
||||
(num_named_args != 0
|
||||
? static_cast<unsigned long long>(detail::has_named_args_bit)
|
||||
: 0);
|
||||
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
|
||||
value_type args_[num_args != 0 ? num_args : +1];
|
||||
|
||||
public:
|
||||
template <typename... T>
|
||||
FMT_CONSTEXPR FMT_INLINE format_arg_store(T&... args)
|
||||
FMT_CONSTEXPR FMT_INLINE format_arg_store_impl(T&... args)
|
||||
:
|
||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
|
||||
basic_format_args<Context>(*this),
|
||||
#endif
|
||||
data_{detail::make_arg<is_packed, Context>(args)...} {
|
||||
if (detail::const_check(num_named_args != 0))
|
||||
detail::init_named_args(data_.named_args(), 0, 0, args...);
|
||||
args_{detail::make_arg<is_packed, Context>(args)...} {
|
||||
}
|
||||
|
||||
static constexpr unsigned long long desc =
|
||||
(is_packed ? detail::encode_types<Context, Args...>()
|
||||
: detail::is_unpacked_bit | num_args);
|
||||
|
||||
FMT_CONSTEXPR FMT_INLINE auto args() const -> const value_type* {
|
||||
return args_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Context, typename... T>
|
||||
using format_arg_store =
|
||||
format_arg_store_impl<Context, detail::count_named_args<T...>(), T...>;
|
||||
|
||||
/**
|
||||
\rst
|
||||
Constructs a `~fmt::format_arg_store` object that contains references to
|
||||
@ -1976,9 +1991,10 @@ class format_arg_store
|
||||
\endrst
|
||||
*/
|
||||
// Arguments are taken by lvalue references to avoid some lifetime issues.
|
||||
template <typename Context = format_context, typename... T>
|
||||
template <typename Context = format_context, typename... T,
|
||||
size_t N = detail::count_named_args<T...>()>
|
||||
constexpr auto make_format_args(T&... args)
|
||||
-> format_arg_store<Context, remove_const_t<T>...> {
|
||||
-> format_arg_store_impl<Context, N, remove_const_t<T>...> {
|
||||
return {args...};
|
||||
}
|
||||
|
||||
@ -2302,9 +2318,10 @@ enum class state { start, align, sign, hash, zero, width, precision, locale };
|
||||
|
||||
// Parses standard format specifiers.
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR FMT_INLINE auto parse_format_specs(
|
||||
const Char* begin, const Char* end, dynamic_format_specs<Char>& specs,
|
||||
basic_format_parse_context<Char>& ctx, type arg_type) -> const Char* {
|
||||
FMT_CONSTEXPR auto parse_format_specs(const Char* begin, const Char* end,
|
||||
dynamic_format_specs<Char>& specs,
|
||||
basic_format_parse_context<Char>& ctx,
|
||||
type arg_type) -> const Char* {
|
||||
auto c = '\0';
|
||||
if (end - begin > 1) {
|
||||
auto next = to_ascii(begin[1]);
|
||||
@ -2742,6 +2759,7 @@ struct formatter<T, Char,
|
||||
public:
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* {
|
||||
if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin();
|
||||
auto type = detail::type_constant<T, Char>::value;
|
||||
auto end =
|
||||
detail::parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, type);
|
||||
|
Loading…
Reference in New Issue
Block a user