https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80662
--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> --- Further reduced: namespace std { // <string> struct string { string(const char* s) : str(s) { } const char* str; }; // <ostream> template<typename C> struct basic_ostream { basic_ostream& operator<<(const char*) { return *this; } }; using ostream = basic_ostream<char>; inline ostream operator<<(ostream& os, const string& s) { os << s.str; return os; } #ifndef UNCONSTRAINED // GCC 7 code template<typename _Tp> struct __is_convertible_to_basic_ostream { template<typename _Ch> static basic_ostream<_Ch>& __check(basic_ostream<_Ch>*); static void __check(void*) = delete; using ostream_type = decltype(__check((_Tp*)0)); }; template<typename _Tp> struct __is_convertible_to_basic_ostream<_Tp&> { }; template<typename _Ostream, typename _Tp> inline typename __is_convertible_to_basic_ostream<_Ostream>::ostream_type operator<<(_Ostream&& __os, const _Tp& __x) { __os << __x; return __os; } #else // GCC 6 code template<typename _CharT, typename _Traits, typename _Tp> inline basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x) { __os << __x; return __os; } #endif } struct my_stream : public std::ostream { template<typename T> my_stream& operator<<(T&& value) { std::ostream::operator<<(value); return *this; } }; int main() { my_stream& s = (my_stream{} << "hello world"); }