https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120625
Bug ID: 120625 Summary: [15/16 Regression] std::formatter<__disabled> specializations cause errors in user code Product: gcc Version: 16.0 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- #include <format> struct X { }; template<typename T> concept is_X = std::is_empty_v<T> && std::is_same_v<X, T>; template<is_X T, typename C> struct std::formatter<T, C> { /* ... */ }; // instantiate the formatter specialization auto s = sizeof(std::formatter<X, char>); This compiles with GCC 14 or with -std=c++20 but not -std=c++23 This is due to: #if defined _GLIBCXX_USE_WCHAR_T && __glibcxx_format_ranges // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3944. Formatters converting sequences of char to sequences of wchar_t namespace __format { struct __disabled; } // std::formatter<__disabled, C> uses the primary template, which is disabled. template<> struct formatter<char*, wchar_t> : private formatter<__format::__disabled, wchar_t> { }; I think we need the __disabled tag type to be complete so that we don't break constraints on program-defined specializations of std::formatter.