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.