[Bug c++/67324] Failures in Assignable concept's requires-expression

pinskia at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Sat Dec 25 01:52:26 GMT 2021


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67324

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
           Keywords|                            |rejects-valid
         Resolution|---                         |FIXED
   Target Milestone|---                         |10.0

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Note this is a fixed up testcase for GCC 10 with -std=c++17 -fconcepts (I don't
know how to fix it up to C++20 syntax though):
  template< typename T, typename U >
  concept bool
    Same( )
  {
    return __is_same_as(T, U);
  }


  template< class T >
    struct remove_reference  { using type = T; };

  template< class U >
    struct remove_reference<U& >  { using type = U; };

  template< class U >
    struct remove_reference<U&&>  { using type = U; };


  template< class T >
    using remove_reference_t = typename remove_reference<T>::type;


  template< typename T >
  constexpr T&&
    forward( remove_reference_t<T>& t) noexcept
  { return static_cast<T&&>(t); }

  template< typename T >
  constexpr T&&
    forward( remove_reference_t<T>&& t) noexcept
  { return static_cast<T&&>(t); }


  template< class T, class U = T >
  concept bool
    Assignable( )
  {
    return
      requires( T&& a, U&& b ) {
        { forward<T>(a) = forward<U>(b) } -> Same<T&>;        // #1
        requires Same<T&, decltype(forward<T>(a) = forward<U>(b))>();  // #2
      };
  }


template< typename T, typename U = T >
constexpr bool
  test( ) { return false; }

template< typename T, typename U = T >
  requires Assignable<T, U>()
constexpr bool
  test( ) { return true; }


struct A { };
struct B { B& operator = ( B const& ) = delete; };
struct C { C& operator = ( C&& ) = delete; };
struct D { D& operator = ( D const& ) = delete; D& operator = ( D&& ) =
default; };
struct E { E& operator = ( E const & ); };
struct F { A& operator = ( F const & ); };


int
  main( )
{
  static_assert( not test<void>(), "" );
  static_assert( test<bool&>(), "" );
  static_assert( not test<int>(), "" );
  static_assert( test<int&>(), "" );
  static_assert( test<int*&>(), "" );
  static_assert( not test<int const&>(), "" );
  static_assert( test<char&>(), "" );
  static_assert( test<unsigned&>(), "" );
  static_assert( test<unsigned long&>(), "" );

  static_assert( test<A&>(), "" );
  static_assert( test<A&,A>(), "" );

  static_assert( not test<B&>(), "" );
  static_assert( not test<B&,B>(), "" );

  static_assert( not test<C&>(), "" );
  static_assert( not test<C&,C>(), "" );

  static_assert( test<D&,D>(), "" );

  static_assert( test<E&,E>(), "" );

  static_assert( not test<F&,F>(), "" );

  return 0;
}

Oh and it is fixed in GCC 10+, most likely by the rewrite of concepts to be
complaint with the C++20 standard.


More information about the Gcc-bugs mailing list