Repository: fmtlib/fmt
File: include/fmt/ranges.h (C/C++)

Code before:
    return it;
  }

  template <typename FormatContext>
  auto format(map_type& map, FormatContext& ctx) const -> decltype(ctx.out()) {
    auto out = ctx.out();
    basic_string_view<Char> open = detail::string_literal<Char, '{'>{};
    if (!no_delimiters_) out = detail::copy<Char>(open, out);
    int i = 0;
    auto mapper = detail::range_mapper<buffered_context<Char>>();
    basic_string_view<Char> sep = detail::string_literal<Char, ',', ' '>{};
    for (auto&& value : map) {
      if (i > 0) out = detail::copy<Char>(sep, out);
      ctx.advance_to(out);
      detail::for_each2(formatters_, mapper.map(value),
                        detail::format_tuple_element<FormatContext>{
                            0, ctx, detail::string_literal<Char, ':', ' '>{}});
      ++i;
    }
    basic_string_view<Char> close = detail::string_literal<Char, '}'>{};
    if (!no_delimiters_) out = detail::copy<Char>(close, out);
    return out;
  }
};

#ifdef __cpp_lib_ranges
// A (debug_)string formatter.
template <typename R, typename Char>
struct formatter<
    R, Char,
    enable_if_t<range_format_kind<R, Char>::value == range_format::string ||
                range_format_kind<R, Char>::value ==
                    range_format::debug_string>> {
 private:
  using range_type = detail::maybe_const_range<R>;
  using string_type = conditional_t<
      std::is_constructible_v<std::basic_string_view<Char>,
                              std::ranges::iterator_t<range_type>,
                              std::ranges::sentinel_t<range_type>>,
      std::basic_string_view<Char>, std::basic_string<Char>>;

  formatter<string_type, Char> underlying_;

 public:
  template <typename ParseContext>
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
    return underlying_.parse(ctx);
  }

  template <typename FormatContext>
  auto format(range_type& range, FormatContext& ctx) const

Review comment (suggestion):
Making this formatter conditional on ranges can be problematic.  {fmt} already has replacement for `std::ranges::begin/end` (`detail::range_begin/end`) so let's use them here.

Code after:
    detail::for_each(formatters_, detail::parse_empty_specs<ParseContext>{ctx});
    return it;
  }

  template <typename FormatContext>
  auto format(map_type& map, FormatContext& ctx) const -> decltype(ctx.out()) {
    auto out = ctx.out();
    basic_string_view<Char> open = detail::string_literal<Char, '{'>{};
    if (!no_delimiters_) out = detail::copy<Char>(open, out);
    int i = 0;
    auto mapper = detail::range_mapper<buffered_context<Char>>();
    basic_string_view<Char> sep = detail::string_literal<Char, ',', ' '>{};
    for (auto&& value : map) {
      if (i > 0) out = detail::copy<Char>(sep, out);
      ctx.advance_to(out);
      detail::for_each2(formatters_, mapper.map(value),
                        detail::format_tuple_element<FormatContext>{
                            0, ctx, detail::string_literal<Char, ':', ' '>{}});
      ++i;
    }
    basic_string_view<Char> close = detail::string_literal<Char, '}'>{};
    if (!no_delimiters_) out = detail::copy<Char>(close, out);
    return out;
  }
};

// A (debug_)string formatter.
template <typename R, typename Char>
struct formatter<
    R, Char,
    enable_if_t<range_format_kind<R, Char>::value == range_format::string ||
                range_format_kind<R, Char>::value ==
                    range_format::debug_string>> {
 private:
  using range_type = detail::maybe_const_range<R>;
#ifdef __cpp_lib_ranges
  using string_type = conditional_t<
      std::is_constructible_v<std::basic_string_view<Char>,
                              std::ranges::iterator_t<range_type>,
                              std::ranges::sentinel_t<range_type>>,
      std::basic_string_view<Char>, std::basic_string<Char>>;
#else
  using string_type = std::basic_string<Char>;
#endif

  formatter<string_type, Char> underlying_;

 public:
  template <typename ParseContext>
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
    return underlying_.parse(ctx);