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>;
```