https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121765
Bug ID: 121765 Summary: `std::formatter` specialization for user-defined type inheriting from `std::formatter<tuple-like>` fails concept `std::formattable` check unexpectedly Product: gcc Version: 16.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: nishuangcheng at gmail dot com Target Milestone: --- The following code causes a compilation error in GCC 15/16, but compiles successfully with Clang and MSVC. See [example](https://godbolt.org/z/3r3enrxEY). ```cpp #include <format> struct S { int i; double d; }; template <> struct std::formatter<S> : std::formatter<std::pair<int, double>> { template <typename FormatContext> auto format(const S& s, FormatContext& ctx) const { return std::formatter<std::pair<int, double>>::format( std::make_pair(s.i, s.d), ctx); } }; static_assert(std::formattable<S, char>); ``` The primary error might be: ``` /opt/compiler-explorer/gcc-trunk-20250902/include/c++/16.0.0/format:5508:21: error: static assertion failed 5508 | static_assert(is_same_v<_Out, __format::_Sink_iter<_CharT>>); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ • 'class std::back_insert_iterator<std::__cxx11::basic_string<char> >' is not the same as 'class std::__format::_Sink_iter<char>' ``` This might be caused by the following code in `<format>`: ```cpp // Output iterator that writes to a type-erase character sink. template<typename _CharT> class _Sink_iter; // An unspecified output iterator type used in the `formattable` concept. template<typename _CharT> struct _Iter_for { using type = back_insert_iterator<basic_string<_CharT>>; }; template<typename _CharT> using __format_context = basic_format_context<_Sink_iter<_CharT>, _CharT>; ```