Fix format_as for tuple-like types with ranges.h (#4945)

This commit is contained in:
Wu Shuwen 2026-09-19 06:16:28 +08:00 committed by GitHub
parent c4fb197284
commit fd0a9b6620
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 1 deletions

View File

@ -297,10 +297,21 @@ template <typename T, typename C> struct is_tuple_formattable {
static constexpr bool value = detail::is_tuple_formattable_<T, C>::value;
};
namespace detail {
template <typename T, typename C, typename = void>
struct is_tuple_formattable_for_formatter
: std::integral_constant<bool, fmt::is_tuple_formattable<T, C>::value> {};
template <typename T, typename C>
struct is_tuple_formattable_for_formatter<T, C, void_t<format_as_result<T>>>
: std::false_type {};
} // namespace detail
template <typename Tuple, typename Char>
struct formatter<Tuple, Char,
enable_if_t<fmt::is_tuple_like<Tuple>::value &&
fmt::is_tuple_formattable<Tuple, Char>::value>> {
detail::is_tuple_formattable_for_formatter<
Tuple, Char>::value>> {
private:
decltype(detail::tuple::get_formatters<Tuple, Char>(
detail::tuple_index_sequence<Tuple>())) formatters_;

View File

@ -721,6 +721,25 @@ TEST(ranges_test, format_as_tie) {
EXPECT_EQ(fmt::format("{}", tieable()), "(3, 0.42)");
}
struct format_as_tuple_like {};
auto format_as(const format_as_tuple_like&) -> std::string { return "Hello"; }
namespace std {
template <> struct tuple_size<format_as_tuple_like>
: integral_constant<size_t, 1> {};
template <> struct tuple_element<0, format_as_tuple_like> {
using type = format_as_tuple_like;
};
} // namespace std
TEST(ranges_test, format_as_tuple_like) {
static_assert(fmt::is_tuple_formattable<format_as_tuple_like, char>::value,
"format_as must not change tuple formattability");
EXPECT_TRUE((fmt::is_formattable<format_as_tuple_like>::value));
EXPECT_EQ(fmt::format("{}", format_as_tuple_like{}), "Hello");
}
struct lvalue_qualified_begin_end {
int arr[5] = {1, 2, 3, 4, 5};