On Tue, 20 Apr 2021, Jonathan Wakely wrote:

> On 19/04/21 22:25 -0400, Patrick Palka via Libstdc++ wrote:
> > This implements the wording changes of P2259R1 "Repairing input range
> > adaptors and counted_iterator", which resolves LWG 3283, 3289 and 3408.
> > 
> > The wording changes are relatively straightforward, but they require
> > some boilerplate to implement: the changes to make a type alias
> > "conditionally present" in some iterator class are realized by defining
> > a base class template and an appropriately constrained partial
> > specialization thereof that contains the type alias, and having the
> > iterator class derive from this base class.  Sometimes the relevant
> > condition depend on members from the iterator class, but because a
> > class is incomplete when instantiating its bases, the constraints on
> > the partial specialization can't use anything from the iterator class.
> > This patch works around this by hoisting these members out to the
> > enclosing scope (e.g. transform_view::_Iterator::_Base is hoisted out
> > to transform_view::_Base so that transform_view::__iter_cat can use it).
> > 
> > This patch also implements the proposed resolution of LWG 3291 to rename
> > iota_view::iterator_category to iota_view::iterator_concept, which was
> > previously problematic due to LWG 3408.
> > 
> > Tested on x86_64-pc-linux-gnu.
> > 
> > libstdc++-v3/ChangeLog:
> > 
> >     PR libstdc++/95983
> >     * include/bits/stl_iterator.h (__detail::__move_iter_cat):
> >     Define.
> >     (move_iterator): Derive from the above in C++20 in order to
> >     conditionally define iterator_category as per P2259.
> >     (move_iterator::__base_cat): No longer used, so remove.
> >     (move_iterator::iterator_category): Remove in C++20.
> >     (__detail::__common_iter_use_postfix_proxy): Define.
> >     (common_iterator::_Proxy): Rename to ...
> >     (common_iterator:__arrow_proxy): ... this.
> >     (common_iterator::__postfix_proxy): Define as per P2259.
> >     (common_iterator::operator->): Adjust.
> >     (common_iterator::operator++): Adjust as per P2259.
> >     (iterator_traits<common_iterator>::_S_iter_cat): Define.
> >     (iterator_traits<common_iterator>::iterator_category): Change as
> >     per P2259.
> >     (__detail::__counted_iter_value_type): Define.
> >     (__detail::__counted_iter_concept): Define.
> >     (__detail::__counted_iter_cat): Define.
> >     (counted_iterator): Derive from the above three classes in order
> >     to conditionally define value_type, iterator_concept and
> >     iterator category respectively as per P2259.
> >     (counted_iterator::operator->): Define as per P2259.
> >     (incrementable_traits<counted_iterator>): Remove as per P2259.
> >     (iterator_traits<counted_iterator>): Adjust as per P2259.
> >     * include/std/ranges (__detail::__iota_view_iter_cat): Define.
> >     (iota_view::_Iterator): Derive from the above in order to
> >     conditionally define iterator_category as per P2259.
> >     (iota_view::_S_iter_cat): Rename to ...
> >     (iota_view::_S_iter_concept): ... this.
> >     (iota_view::iterator_concept): Use it to apply LWG 3291 changes.
> >     (iota_view::iterator_category): Remove.
> >     (__detail::__filter_view_iter_cat): Define.
> >     (filter_view::_Iterator): Derive from the above in order to
> >     conditionally define iterator_category as per P2259.
> >     (filter_view::_Iterator): Move to struct __filter_view_iter_cat.
> >     (filter_view::_Iterator::iterator_category): Remove.
> >     (transform_view::_Base): Define.
> >     (transform_view::__iter_cat): Define.
> >     (transform_view::_Iterator): Derive from the above in order to
> >     conditionally define iterator_category as per P2259.
> >     (transform_view::_Iterator::_Base): Just alias
> >     transform_view::_Base.
> >     (transform_view::_Iterator::_S_iter_cat): Move to struct
> >     transform_view::__iter_cat.
> >     (transform_view::_Iterator::iterator_category): Remove.
> >     (transform_view::_Sentinel::_Base): Just alias
> >     transform_view::_Base.
> >     (join_view::_Base): Define.
> >     (join_view::_Outer_iter): Define.
> >     (join_view::_Inner_iter): Define.
> >     (join_view::_S_ref_is_glvalue): Define.
> >     (join_view::__iter_cat): Define.
> >     (join_view::_Iterator): Derive from it in order to conditionally
> >     define iterator_category as per P2259.
> >     (join_view::_Iterator::_Base): Just alias join_view::_Base.
> >     (join_view::_Iterator::_S_ref_is_glvalue): Just alias
> >     join_view::_S_ref_is_glvalue.
> >     (join_view::_Iterator::_S_iter_cat): Move to struct
> >     transform_view::__iter_cat.
> >     (join_view::_Iterator::_Outer_iter): Just alias
> >     join_view::_Outer_iter.
> >     (join_view::_Iterator::_Inner_iter): Just alias
> >     join_view::_Inner_iter.
> >     (join_view::_Iterator::iterator_category): Remove.
> >     (join_view::_Sentinel::_Base): Just alias join_view::_Base.
> >     (__detail::__split_view_outer_iter_cat): Define.
> >     (__detail::__split_view_inner_iter_cat): Define.
> >     (split_view::_Base): Define.
> >     (split_view::_Outer_iter): Derive from __split_view_outer_iter_cat
> >     in order to conditionally define iterator_category as per P2259.
> >     (split_view::_Outer_iter::iterator_category): Remove.
> >     (split_view::_Inner_iter): Derive from __split_view_inner_iter_cat
> >     in order to conditionally define iterator_category as per P2259.
> >     (split_view::_Inner_iter::_S_iter_cat): Move to
> >     __split_view_inner_iter_cat.
> >     (split_view::_Inner_iter::iterator_category): Remove.
> >     (elements_view::_Base): Define.
> >     (elements_view::__iter_cat): Define.
> >     (elements_view::_Iterator): Derive from the above in order to
> >     conditionall define iterator_category as per P2259.
> >     (elements_view::_Iterator::_Base): Just alias
> >     elements_view::_Base.
> >     (elements_view::_Iterator::_S_iter_concept)
> >     (elements_view::_Iterator::iterator_concept): Define as per
> >     P2259.
> >     (elements_view::_Iterator::iterator_category): Remove.
> >     (elements_view::_Sentinel::_Base): Just alias
> >     elements_view::_Base.
> >     * testsuite/24_iterators/headers/iterator/synopsis_c++20: Adjust
> >     constraints on iterator_traits<counted_iterator>.
> >     * testsuite/std/ranges/p2259.cc: New test.
> > ---
> > libstdc++-v3/include/bits/stl_iterator.h      | 128 ++++++--
> > libstdc++-v3/include/std/ranges               | 299 ++++++++++++------
> > .../headers/iterator/synopsis_c++20.cc        |   1 +
> > libstdc++-v3/testsuite/std/ranges/p2259.cc    |  91 ++++++
> > 4 files changed, 412 insertions(+), 107 deletions(-)
> > create mode 100644 libstdc++-v3/testsuite/std/ranges/p2259.cc
> > 
> > diff --git a/libstdc++-v3/include/bits/stl_iterator.h
> > b/libstdc++-v3/include/bits/stl_iterator.h
> > index dc8b101e8f8..049f83cff90 100644
> > --- a/libstdc++-v3/include/bits/stl_iterator.h
> > +++ b/libstdc++-v3/include/bits/stl_iterator.h
> > @@ -1302,6 +1302,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >     };
> > #endif // C++20
> > 
> > +  namespace __detail
> > +  {
> > +#if __cplusplus > 201703L && __cpp_lib_concepts
> > +    template<typename _Iterator>
> > +      struct __move_iter_cat
> > +      { };
> > +
> > +    template<typename _Iterator>
> > +      requires requires { typename
> > iterator_traits<_Iterator>::iterator_category; }
> > +      struct __move_iter_cat<_Iterator>
> > +      {
> > +   using iterator_category
> > +     = __clamp_iter_cat<typename
> > iterator_traits<_Iterator>::iterator_category,
> > +                        random_access_iterator_tag>;
> > +      };
> > +#endif
> > +  }
> > +
> >   // 24.4.3  Move iterators
> >   /**
> >    *  Class template move_iterator is an iterator adapter with the same
> > @@ -1313,13 +1331,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >    */
> >   template<typename _Iterator>
> >     class move_iterator
> > +#if __cplusplus > 201703L && __cpp_lib_concepts
> > +      : public __detail::__move_iter_cat<_Iterator>
> > +#endif
> >     {
> >       _Iterator _M_current;
> > 
> >       using __traits_type = iterator_traits<_Iterator>;
> > -#if __cplusplus > 201703L && __cpp_lib_concepts
> > -      using __base_cat = typename __traits_type::iterator_category;
> > -#else
> > +#if ! (__cplusplus > 201703L && __cpp_lib_concepts)
> 
> These preprocessor conditionals would be simpler if we just used
> __cpp_lib_concepts instead of (C++20 && __cpp_lib_concepts). That
> would be fine, because __cpp_lib_concepts is only defined for C++20
> anyway. But we can change that later, not as part of this patch.

Sounds good.

> 
> >       using __base_ref = typename __traits_type::reference;
> > #endif
> > 
> 
> OK for trunk and gcc-11 branch, thanks.

Thanks a lot, committed!

> 
> We should also look into whether backporting to gcc-10 is feasible. I
> think it should be, but I didn't try.

I bet it would be modulo some small LWG issue fixes that I may have not
yet backported to the 10 branch.  I'll take a look :)

Reply via email to