diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index 2ea1c125..46262e73 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -582,6 +582,33 @@ template struct is_range { !std::is_constructible, T>::value; }; +namespace detail { +template struct range_mapper { + using mapper = arg_mapper; + + template , Context>::value)> + static auto map(T&& value) -> T&& { + return static_cast(value); + } + template , Context>::value)> + static auto map(T&& value) + -> decltype(mapper().map(static_cast(value))) { + return mapper().map(static_cast(value)); + } +}; + +template +using range_formatter_type = + conditional_t::value, + formatter, Element>{} + .map(std::declval()))>, + Char>, + fallback_formatter>; +} // namespace detail + template struct formatter< R, Char, @@ -594,26 +621,8 @@ struct formatter< #endif >> { - using context = buffer_context; - using mapper = detail::arg_mapper; - using element = detail::uncvref_type; - - template , context>::value)> - static auto map(T&& value) -> T&& { - return static_cast(value); - } - template , context>::value)> - static auto map(T&& value) - -> decltype(mapper().map(static_cast(value))) { - return mapper().map(static_cast(value)); - } - - using formatter_type = conditional_t< - is_formattable::value, - formatter()))>, Char>, - detail::fallback_formatter>; + using formatter_type = + detail::range_formatter_type>; formatter_type underlying_; bool custom_specs_ = false; @@ -621,14 +630,10 @@ struct formatter< FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { auto it = ctx.begin(); auto end = ctx.end(); - if (it == end || *it == '}') { - return it; - } + if (it == end || *it == '}') return it; - if (*it != ':') { - // no top-level range formatters yet + if (*it != ':') throw format_error("no top-level range formatters supported"); - } custom_specs_ = true; ++it;