https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99692
Jonathan Wakely <redi at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Ever confirmed|0 |1 See Also| |https://gcc.gnu.org/bugzill | |a/show_bug.cgi?id=51577 Status|UNCONFIRMED |NEW Last reconfirmed| |2021-05-06 --- Comment #10 from Jonathan Wakely <redi at gcc dot gnu.org> --- Reduced: namespace std { struct ostream { }; template<typename T> T&& declval(); template<typename...> using void_t = void; struct false_type { static constexpr bool value = false; }; struct true_type { static constexpr bool value = true; }; template<bool, typename = void> struct enable_if { }; template<typename T> struct enable_if<true, T> { using type = T; }; void __is_convertible_to_basic_ostream_test(ostream*); template<typename _Tp, typename = void> struct __is_convertible_to_basic_ostream : false_type { }; template<typename _Tp> struct __is_convertible_to_basic_ostream<_Tp, decltype(__is_convertible_to_basic_ostream_test(declval<_Tp*>()))> : true_type { using __ostream_type = ostream&; }; template<typename _Tp> struct __is_convertible_to_basic_ostream<_Tp&> : false_type { using __ostream_type = void; }; template<typename _Ostream, typename _Tp, typename = void> struct __is_insertable : false_type {}; template<typename _Ostream, typename _Tp> struct __is_insertable<_Ostream, _Tp, void_t<decltype(declval<_Ostream&>() << declval<const _Tp&>())>> : true_type {}; template<typename _Ostream> using __rvalue_ostream_type = typename __is_convertible_to_basic_ostream< _Ostream>::__ostream_type; template<typename _Ostream, typename _Tp> inline typename enable_if<__is_convertible_to_basic_ostream<_Ostream>::value && __is_insertable<__rvalue_ostream_type<_Ostream>, const _Tp&>::value, __rvalue_ostream_type<_Ostream>>::type operator<<(_Ostream&& __os, const _Tp&) { return __os; } } struct CustomStream : std::ostream {}; namespace N { class A{}; } std::ostream& operator<<(std::ostream& s, const N::A&) { return s; } CustomStream& operator<<(CustomStream&& s, const N::A&) { return s; } int main() { CustomStream() << N::A{}; } Clang accepts this, GCC doesn't.