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.

Reply via email to