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>();
}
```

Reply via email to