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

Code before:
      out = std::copy(value.sep.begin(), value.sep.end(), out);
      ctx.advance_to(out);
      return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
    }
    return out;
  }
};

namespace detail {
// Check if T has an interface like container adapter (e.g. std::stack,
// std::queue, std::priority_queue).
template <typename T> class is_container_adaptor_like {
  template <typename U> static auto check(U* p) -> typename U::container_type;
  template <typename> static void check(...);

 public:
  static constexpr const bool value =
      !std::is_void<decltype(check<T>(nullptr))>::value;
};
}  // namespace detail

template <typename T, typename Char>
struct formatter<T, Char,
                 enable_if_t<detail::is_container_adaptor_like<T>::value>> {
 private:
    struct formatter<typename T::container_type, Char> container_formatter;

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

  template <typename FormatContext>
  auto format(T& t, FormatContext& ctx) const ->
      typename FormatContext::iterator {
    struct getter : T {
      static auto get(T& t) -> typename T::container_type& {
        return t.*(&getter::c);  // Access c through the derived class.
      }
    };
    return container_formatter.format(getter::get(t), ctx);
  }
};

FMT_MODULE_EXPORT_BEGIN

/**
  \rst
  Returns an object that formats `tuple` with elements separated by `sep`.


Review comment (suggestion):
`struct` not needed here and I suggest using inheritance instead of composition to avoid redefining `parse`.

Also please apply clang-format, indent is a bit off.

Code after:
      out = std::copy(value.sep.begin(), value.sep.end(), out);
      ctx.advance_to(out);
      return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
    }
    return out;
  }
};

namespace detail {
// Check if T has an interface like container adapter (e.g. std::stack,
// std::queue, std::priority_queue).
template <typename T> class is_container_adaptor_like {
  template <typename U> static auto check(U* p) -> typename U::container_type;
  template <typename> static void check(...);

 public:
  static constexpr const bool value =
      !std::is_void<decltype(check<T>(nullptr))>::value;
};
}  // namespace detail

template <typename T, typename Char>
struct formatter<T, Char,
                 enable_if_t<detail::is_container_adaptor_like<T>::value>>
    : formatter<typename T::container_type, Char> {
  template <typename FormatContext>
  auto format(const T& t, FormatContext& ctx) const -> decltype(ctx.out()) {
    struct getter : T {
      static auto get(const T& t) -> const typename T::container_type& {
        return t.*(&getter::c);  // Access c through the derived class.
      }
    };
    return formatter<typename T::container_type>::format(getter::get(t), ctx);
  }
};

FMT_MODULE_EXPORT_BEGIN

/**
  \rst
  Returns an object that formats `tuple` with elements separated by `sep`.

  **Example**::

    std::tuple<int, char> t = {1, 'a'};
    fmt::print("{}", fmt::join(t, ", "));
    // Output: "1, a"
  \endrst
 */
template <typename... T>
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)