On Thu, 27 Feb 2025, Jonathan Wakely wrote:

> On Thu, 27 Feb 2025 at 20:52, Patrick Palka <ppa...@redhat.com> wrote:
> >
> > Tested on x86_64-pc-linux-gnu, does this look OK for trunk and perhaps
> > 14?
> 
> OK for both.

Thanks.

> 
> Do we want a library issue for this? The "buggy" code you're changing
> is exactly what the standard says.

I think so, I'll submit one.  It seems like a GCC specific issue
only because we're still the only ones to implement CWG 2369 AFAICT.

> 
> 
> >
> > -- >8 --
> >
> > Here for
> >
> >   using RCI = reverse_iterator<basic_const_iterator<vector<int>::iterator>>
> >   static_assert(std::totally_ordered<RCI>);
> >
> > we effectively need to check the requirement
> >
> >   requires (RCI x) { x RELOP x; }  for each RELOP in {<, >, <=, >=}
> >
> > which we expect to be straightforwardly satisfied by reverse_iterator's
> > namespace-scope relops.  But due to ADL we find ourselves also
> > considering the basic_const_iterator relop friends, which before CWG
> > 2369 would be quickly discarded since RCI clearly isn't convertible to
> > basic_const_iterator.  After CWG 2369 though we must first check these
> > relops' constraints (with _It = vector<int>::iterator and _It2 = RCI),
> > which entails checking totally_ordered<RCI> recursively.
> >
> > This patch fixes this by turning the problematic non-dependent parameter
> > of type basic_const_iterator<_It> into a dependent parameter of type
> > basic_const_iterator<_It3> where _It3 is constrained to match _It.
> > Thus the basic_const_iterator relop friends now get quickly discarded
> > during deduction since RCI isn't a specialization of basic_const_iterator
> > (or derived from one) and so _It3 is not deduced.
> >
> >         PR libstdc++/112490
> >
> > libstdc++-v3/ChangeLog:
> >
> >         * include/bits/stl_iterator.h (basic_const_iterator::operator<):
> >         Replace non-dependent basic_const_iterator parameter with
> >         a dependent one of type basic_const_iterator<_It3>.  Constrain
> >         _It3 to match _It.
> >         (basic_const_iterator::operator>): Likewise.
> >         (basic_const_iterator::operator<=): Likewise.
> >         (basic_const_iterator::operator>=): Likewise.
> >         * testsuite/24_iterators/const_iterator/112490.cc: New test.
> > ---
> >  libstdc++-v3/include/bits/stl_iterator.h         | 16 ++++++++--------
> >  .../24_iterators/const_iterator/112490.cc        | 12 ++++++++++++
> >  2 files changed, 20 insertions(+), 8 deletions(-)
> >  create mode 100644 
> > libstdc++-v3/testsuite/24_iterators/const_iterator/112490.cc
> >
> > diff --git a/libstdc++-v3/include/bits/stl_iterator.h 
> > b/libstdc++-v3/include/bits/stl_iterator.h
> > index 3e025342fb5..33732b1a428 100644
> > --- a/libstdc++-v3/include/bits/stl_iterator.h
> > +++ b/libstdc++-v3/include/bits/stl_iterator.h
> > @@ -2881,30 +2881,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >         && three_way_comparable_with<_It, _It2>
> >        { return _M_current <=> __y; }
> >
> > -    template<__detail::__not_a_const_iterator _It2>
> > +    template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3>
> >        friend constexpr bool
> > -      operator<(const _It2& __x, const basic_const_iterator& __y)
> > +      operator<(const _It2& __x, const basic_const_iterator<_It3>& __y)
> >        noexcept(noexcept(__x < __y._M_current))
> >        requires random_access_iterator<_It> && totally_ordered_with<_It, 
> > _It2>
> >        { return __x < __y._M_current; }
> >
> > -    template<__detail::__not_a_const_iterator _It2>
> > +    template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3>
> >        friend constexpr bool
> > -      operator>(const _It2& __x, const basic_const_iterator& __y)
> > +      operator>(const _It2& __x, const basic_const_iterator<_It3>& __y)
> >        noexcept(noexcept(__x > __y._M_current))
> >        requires random_access_iterator<_It> && totally_ordered_with<_It, 
> > _It2>
> >        { return __x > __y._M_current; }
> >
> > -    template<__detail::__not_a_const_iterator _It2>
> > +    template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3>
> >        friend constexpr bool
> > -      operator<=(const _It2& __x, const basic_const_iterator& __y)
> > +      operator<=(const _It2& __x, const basic_const_iterator<_It3>& __y)
> >        noexcept(noexcept(__x <= __y._M_current))
> >        requires random_access_iterator<_It> && totally_ordered_with<_It, 
> > _It2>
> >        { return __x <= __y._M_current; }
> >
> > -    template<__detail::__not_a_const_iterator _It2>
> > +    template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3>
> >        friend constexpr bool
> > -      operator>=(const _It2& __x, const basic_const_iterator& __y)
> > +      operator>=(const _It2& __x, const basic_const_iterator<_It3>& __y)
> >        noexcept(noexcept(__x >= __y._M_current))
> >        requires random_access_iterator<_It> && totally_ordered_with<_It, 
> > _It2>
> >        { return __x >= __y._M_current; }
> > diff --git a/libstdc++-v3/testsuite/24_iterators/const_iterator/112490.cc 
> > b/libstdc++-v3/testsuite/24_iterators/const_iterator/112490.cc
> > new file mode 100644
> > index 00000000000..9bb154847cf
> > --- /dev/null
> > +++ b/libstdc++-v3/testsuite/24_iterators/const_iterator/112490.cc
> > @@ -0,0 +1,12 @@
> > +// { dg-do compile { target c++23 } }
> > +
> > +// PR libstdc++/112490 - infinite meta error in
> > +// reverse_iterator<basic_const_iterator<vector<int>::iterator>>
> > +
> > +#include <iterator>
> > +#include <vector>
> > +
> > +using I = std::vector<int>::iterator;
> > +using CI = std::basic_const_iterator<I>;
> > +using RCI = std::reverse_iterator<CI>;
> > +static_assert(std::totally_ordered<RCI>);
> > --
> > 2.49.0.rc0
> >
> 
> 

Reply via email to