I’ve verified it and libc++ is indeed wrong, however I’m not convinced whether this is worth fixing:
C++20 has a textual requirement for what a proper std::formatter specialization is.
C++23 ranges has a formattable concept.
Your formatter satisfies the C++20 requirements, but not the C++23 concept as implemented by libstdc++ and libc++. (Compiler Explorer) So when you want to format a std::vector<Foo> it correctly fails on libc++. (On libstdc++ it fails, because they don’t have a formatter for std::vector yet.)
The easiest fix for you would be to use auto format(const Foo& obj, auto& ctx) const as format member function.
I will give this some more thoughts, to see what the best solution is. (There is a bit of an issue with the concept, so your formatter might be formattable on MSVC STL if they make different design choices. In fact it’s possible to create a formatter that’s formattable for libc++ but not for libstdc++.)
It’s failing since formatters are expected to work with different format_context’s. So creating a formatter only for std::format_context is not very generic. The context depends the type of output iterator used.
I was having the same problem. Looked at how libc++ was implemented internally and found they use auto instead of std::format_context in the format function. Make that change and the specialization works.