https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99599
--- Comment #15 from danakj at orodu dot net --- The workaround listed in Comment #6 does not work for templated types, unfortunately, making Clang and MSVC more expressive here than GCC. https://godbolt.org/z/obhsqhrbx ``` #include <concepts> #include <sstream> #include <string> #if defined(__GNUC__) && !defined(__clang__) #define COMPILER_IS_GCC 1 #else #define COMPILER_IS_GCC 0 #endif namespace sus::string::__private { template <class A, class B> A& format_to_stream(A&, B); template <class T, class Char> concept StreamCanReceiveString = requires(T& t, std::basic_string<Char> s) { { operator<<(t, s) }; }; /// Consumes the string `s` and streams it to the output stream `os`. template <class Char, StreamCanReceiveString<Char> S> S& format_to_stream(S& os, const std::basic_string<Char>& s) { os << s; return os; } } // namespace sus::string::__private namespace sus::option { template <class T> class Option {}; using namespace ::sus::string::__private; template < class T, #if COMPILER_IS_GCC std::same_as<Option<T> > Sus_ValueType, // Does not deduce T. ***** #endif StreamCanReceiveString<char> Sus_StreamType > inline Sus_StreamType& operator<<( Sus_StreamType& stream, #if COMPILER_IS_GCC const Sus_ValueType& value #else const ::sus::option::Option<T>& value // Does deduce T. **** #endif ) { return format_to_stream(stream, std::string()); } } // namespace sus::option int main() { std::stringstream s; s << sus::option::Option<int>(); } ```