diff mbox series

libstdc++: Implement LWG 3798 for range adaptors [PR106676]

Message ID 20241013235316.1722410-1-jwakely@redhat.com
State New
Headers show
Series libstdc++: Implement LWG 3798 for range adaptors [PR106676] | expand

Commit Message

Jonathan Wakely Oct. 13, 2024, 11:53 p.m. UTC
Tested x86_64-linux.

-- >8 --

LWG 3798 modified the iterator_category of the iterator types for
transform_view, join_with_view, zip_transform_view and
adjacent_transform_view, to allow the iterator's reference type to be an
rvalue reference.

libstdc++-v3/ChangeLog:

	PR libstdc++/106676
	* include/bits/iterator_concepts.h (__cpp17_fwd_iterator): Use
	is_reference instead of is_value_reference.
	rvalue references.
	* include/std/ranges (transform_view:__iter_cat::_S_iter_cat):
	Likewise.
	(zip_transform_view::__iter_cat::_S_iter_cat): Likewise.
	(adjacent_transform_view::__iter_cat::_S_iter_cat): Likewise.
	(join_with_view::__iter_cat::_S_iter_cat): Likewise.
	* testsuite/std/ranges/adaptors/transform.cc: Check
	iterator_category when the transformation function returns an
	rvalue reference type.
---
 libstdc++-v3/include/bits/iterator_concepts.h    |  4 +++-
 libstdc++-v3/include/std/ranges                  | 16 ++++++++++++----
 .../testsuite/std/ranges/adaptors/transform.cc   | 16 ++++++++++++++++
 3 files changed, 31 insertions(+), 5 deletions(-)

Comments

Patrick Palka Oct. 15, 2024, 1:30 p.m. UTC | #1
On Mon, 14 Oct 2024, Jonathan Wakely wrote:

> Tested x86_64-linux.
> 
> -- >8 --
> 
> LWG 3798 modified the iterator_category of the iterator types for
> transform_view, join_with_view, zip_transform_view and
> adjacent_transform_view, to allow the iterator's reference type to be an
> rvalue reference.
> 
> libstdc++-v3/ChangeLog:
> 
> 	PR libstdc++/106676
> 	* include/bits/iterator_concepts.h (__cpp17_fwd_iterator): Use
> 	is_reference instead of is_value_reference.
> 	rvalue references.
> 	* include/std/ranges (transform_view:__iter_cat::_S_iter_cat):
> 	Likewise.
> 	(zip_transform_view::__iter_cat::_S_iter_cat): Likewise.
> 	(adjacent_transform_view::__iter_cat::_S_iter_cat): Likewise.
> 	(join_with_view::__iter_cat::_S_iter_cat): Likewise.
> 	* testsuite/std/ranges/adaptors/transform.cc: Check
> 	iterator_category when the transformation function returns an
> 	rvalue reference type.
> ---
>  libstdc++-v3/include/bits/iterator_concepts.h    |  4 +++-
>  libstdc++-v3/include/std/ranges                  | 16 ++++++++++++----
>  .../testsuite/std/ranges/adaptors/transform.cc   | 16 ++++++++++++++++
>  3 files changed, 31 insertions(+), 5 deletions(-)
> 
> diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
> index 490a362cdf1..669d3ddfd1e 100644
> --- a/libstdc++-v3/include/bits/iterator_concepts.h
> +++ b/libstdc++-v3/include/bits/iterator_concepts.h
> @@ -333,10 +333,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  	    typename incrementable_traits<_Iter>::difference_type>;
>  	};
>  
> +    // _GLIBCXX_RESOLVE_LIB_DEFECTS
> +    // 3798. Rvalue reference and iterator_category
>      template<typename _Iter>
>        concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter>
>  	&& constructible_from<_Iter>
> -	&& is_lvalue_reference_v<iter_reference_t<_Iter>>
> +	&& is_reference_v<iter_reference_t<_Iter>>
>  	&& same_as<remove_cvref_t<iter_reference_t<_Iter>>,
>  		   typename indirectly_readable_traits<_Iter>::value_type>
>  	&& requires(_Iter __it)
> diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
> index f0d81cbea0c..941189d65c3 100644
> --- a/libstdc++-v3/include/std/ranges
> +++ b/libstdc++-v3/include/std/ranges
> @@ -1892,7 +1892,9 @@ namespace views::__adaptor
>  	    using _Fpc = __detail::__maybe_const_t<_Const, _Fp>;
>  	    using _Base = transform_view::_Base<_Const>;
>  	    using _Res = invoke_result_t<_Fpc&, range_reference_t<_Base>>;
> -	    if constexpr (is_lvalue_reference_v<_Res>)
> +	    // _GLIBCXX_RESOLVE_LIB_DEFECTS
> +	    // 3798. Rvalue reference and iterator_category
> +	    if constexpr (is_reference_v<_Res>)
>  	      {
>  		using _Cat
>  		  = typename iterator_traits<iterator_t<_Base>>::iterator_category;
> @@ -5047,7 +5049,9 @@ namespace views::__adaptor
>  	  using __detail::__range_iter_cat;
>  	  using _Res = invoke_result_t<__maybe_const_t<_Const, _Fp>&,
>  				       range_reference_t<__maybe_const_t<_Const, _Vs>>...>;
> -	  if constexpr (!is_lvalue_reference_v<_Res>)
> +	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
> +	  // 3798. Rvalue reference and iterator_category
> +	  if constexpr (!is_reference_v<_Res>)
>  	    return input_iterator_tag{};
>  	  else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>,
>  					   random_access_iterator_tag> && ...))
> @@ -5820,7 +5824,9 @@ namespace views::__adaptor
>        using _Res = invoke_result_t<__unarize<__maybe_const_t<_Const, _Fp>&, _Nm>,
>  				   range_reference_t<_Base>>;
>        using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category;
> -      if constexpr (!is_lvalue_reference_v<_Res>)
> +      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> +      // 3798. Rvalue reference and iterator_category
> +      if constexpr (!is_reference_v<_Res>)
>  	return input_iterator_tag{};
>        else if constexpr (derived_from<_Cat, random_access_iterator_tag>)
>  	return random_access_iterator_tag{};
> @@ -7228,7 +7234,9 @@ namespace views::__adaptor
>  	  using _OuterCat = typename iterator_traits<_OuterIter>::iterator_category;
>  	  using _InnerCat = typename iterator_traits<_InnerIter>::iterator_category;
>  	  using _PatternCat = typename iterator_traits<_PatternIter>::iterator_category;
> -	  if constexpr (!is_lvalue_reference_v<common_reference_t<iter_reference_t<_InnerIter>,
> +	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
> +	  // 3798. Rvalue reference and iterator_category
> +	  if constexpr (!is_reference_v<common_reference_t<iter_reference_t<_InnerIter>,
>  								  iter_reference_t<_PatternIter>>>)

This line is misaligned with the previous one now.  LGTM besides that

>  	    return input_iterator_tag{};
>  	  else if constexpr (derived_from<_OuterCat, bidirectional_iterator_tag>
> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
> index ca695349650..e1b74353e63 100644
> --- a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
> @@ -214,6 +214,21 @@ test10()
>    static_assert(std::same_as<cat, std::random_access_iterator_tag>);
>  }
>  
> +void
> +test11()
> +{
> +  struct MoveIt {
> +    int&& operator()(int& i) const { return std::move(i); }
> +  };
> +
> +  int x[] {2, 4};
> +  auto xform = x | views::transform(MoveIt{});
> +  using iterator = decltype(xform.begin());
> +  // LWG 3798. Rvalue reference and iterator_category
> +  using cat = std::iterator_traits<iterator>::iterator_category;
> +  static_assert(std::same_as<cat, std::random_access_iterator_tag>);
> +}
> +
>  int
>  main()
>  {
> @@ -227,4 +242,5 @@ main()
>    test08();
>    test09();
>    test10();
> +  test11();
>  }
> -- 
> 2.46.2
> 
>
Jonathan Wakely Oct. 15, 2024, 1:46 p.m. UTC | #2
On Tue, 15 Oct 2024 at 14:30, Patrick Palka <ppalka@redhat.com> wrote:
>
> On Mon, 14 Oct 2024, Jonathan Wakely wrote:
>
> > Tested x86_64-linux.
> >
> > -- >8 --
> >
> > LWG 3798 modified the iterator_category of the iterator types for
> > transform_view, join_with_view, zip_transform_view and
> > adjacent_transform_view, to allow the iterator's reference type to be an
> > rvalue reference.
> >
> > libstdc++-v3/ChangeLog:
> >
> >       PR libstdc++/106676
> >       * include/bits/iterator_concepts.h (__cpp17_fwd_iterator): Use
> >       is_reference instead of is_value_reference.
> >       rvalue references.
> >       * include/std/ranges (transform_view:__iter_cat::_S_iter_cat):
> >       Likewise.
> >       (zip_transform_view::__iter_cat::_S_iter_cat): Likewise.
> >       (adjacent_transform_view::__iter_cat::_S_iter_cat): Likewise.
> >       (join_with_view::__iter_cat::_S_iter_cat): Likewise.
> >       * testsuite/std/ranges/adaptors/transform.cc: Check
> >       iterator_category when the transformation function returns an
> >       rvalue reference type.
> > ---
> >  libstdc++-v3/include/bits/iterator_concepts.h    |  4 +++-
> >  libstdc++-v3/include/std/ranges                  | 16 ++++++++++++----
> >  .../testsuite/std/ranges/adaptors/transform.cc   | 16 ++++++++++++++++
> >  3 files changed, 31 insertions(+), 5 deletions(-)
> >
> > diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
> > index 490a362cdf1..669d3ddfd1e 100644
> > --- a/libstdc++-v3/include/bits/iterator_concepts.h
> > +++ b/libstdc++-v3/include/bits/iterator_concepts.h
> > @@ -333,10 +333,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >           typename incrementable_traits<_Iter>::difference_type>;
> >       };
> >
> > +    // _GLIBCXX_RESOLVE_LIB_DEFECTS
> > +    // 3798. Rvalue reference and iterator_category
> >      template<typename _Iter>
> >        concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter>
> >       && constructible_from<_Iter>
> > -     && is_lvalue_reference_v<iter_reference_t<_Iter>>
> > +     && is_reference_v<iter_reference_t<_Iter>>
> >       && same_as<remove_cvref_t<iter_reference_t<_Iter>>,
> >                  typename indirectly_readable_traits<_Iter>::value_type>
> >       && requires(_Iter __it)
> > diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
> > index f0d81cbea0c..941189d65c3 100644
> > --- a/libstdc++-v3/include/std/ranges
> > +++ b/libstdc++-v3/include/std/ranges
> > @@ -1892,7 +1892,9 @@ namespace views::__adaptor
> >           using _Fpc = __detail::__maybe_const_t<_Const, _Fp>;
> >           using _Base = transform_view::_Base<_Const>;
> >           using _Res = invoke_result_t<_Fpc&, range_reference_t<_Base>>;
> > -         if constexpr (is_lvalue_reference_v<_Res>)
> > +         // _GLIBCXX_RESOLVE_LIB_DEFECTS
> > +         // 3798. Rvalue reference and iterator_category
> > +         if constexpr (is_reference_v<_Res>)
> >             {
> >               using _Cat
> >                 = typename iterator_traits<iterator_t<_Base>>::iterator_category;
> > @@ -5047,7 +5049,9 @@ namespace views::__adaptor
> >         using __detail::__range_iter_cat;
> >         using _Res = invoke_result_t<__maybe_const_t<_Const, _Fp>&,
> >                                      range_reference_t<__maybe_const_t<_Const, _Vs>>...>;
> > -       if constexpr (!is_lvalue_reference_v<_Res>)
> > +       // _GLIBCXX_RESOLVE_LIB_DEFECTS
> > +       // 3798. Rvalue reference and iterator_category
> > +       if constexpr (!is_reference_v<_Res>)
> >           return input_iterator_tag{};
> >         else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>,
> >                                          random_access_iterator_tag> && ...))
> > @@ -5820,7 +5824,9 @@ namespace views::__adaptor
> >        using _Res = invoke_result_t<__unarize<__maybe_const_t<_Const, _Fp>&, _Nm>,
> >                                  range_reference_t<_Base>>;
> >        using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category;
> > -      if constexpr (!is_lvalue_reference_v<_Res>)
> > +      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> > +      // 3798. Rvalue reference and iterator_category
> > +      if constexpr (!is_reference_v<_Res>)
> >       return input_iterator_tag{};
> >        else if constexpr (derived_from<_Cat, random_access_iterator_tag>)
> >       return random_access_iterator_tag{};
> > @@ -7228,7 +7234,9 @@ namespace views::__adaptor
> >         using _OuterCat = typename iterator_traits<_OuterIter>::iterator_category;
> >         using _InnerCat = typename iterator_traits<_InnerIter>::iterator_category;
> >         using _PatternCat = typename iterator_traits<_PatternIter>::iterator_category;
> > -       if constexpr (!is_lvalue_reference_v<common_reference_t<iter_reference_t<_InnerIter>,
> > +       // _GLIBCXX_RESOLVE_LIB_DEFECTS
> > +       // 3798. Rvalue reference and iterator_category
> > +       if constexpr (!is_reference_v<common_reference_t<iter_reference_t<_InnerIter>,
> >                                                                 iter_reference_t<_PatternIter>>>)
>
> This line is misaligned with the previous one now.  LGTM besides that

Ah yes, good catch. I'll fix and push, thanks.


>
> >           return input_iterator_tag{};
> >         else if constexpr (derived_from<_OuterCat, bidirectional_iterator_tag>
> > diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
> > index ca695349650..e1b74353e63 100644
> > --- a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
> > +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
> > @@ -214,6 +214,21 @@ test10()
> >    static_assert(std::same_as<cat, std::random_access_iterator_tag>);
> >  }
> >
> > +void
> > +test11()
> > +{
> > +  struct MoveIt {
> > +    int&& operator()(int& i) const { return std::move(i); }
> > +  };
> > +
> > +  int x[] {2, 4};
> > +  auto xform = x | views::transform(MoveIt{});
> > +  using iterator = decltype(xform.begin());
> > +  // LWG 3798. Rvalue reference and iterator_category
> > +  using cat = std::iterator_traits<iterator>::iterator_category;
> > +  static_assert(std::same_as<cat, std::random_access_iterator_tag>);
> > +}
> > +
> >  int
> >  main()
> >  {
> > @@ -227,4 +242,5 @@ main()
> >    test08();
> >    test09();
> >    test10();
> > +  test11();
> >  }
> > --
> > 2.46.2
> >
> >
>
diff mbox series

Patch

diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index 490a362cdf1..669d3ddfd1e 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -333,10 +333,12 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    typename incrementable_traits<_Iter>::difference_type>;
 	};
 
+    // _GLIBCXX_RESOLVE_LIB_DEFECTS
+    // 3798. Rvalue reference and iterator_category
     template<typename _Iter>
       concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter>
 	&& constructible_from<_Iter>
-	&& is_lvalue_reference_v<iter_reference_t<_Iter>>
+	&& is_reference_v<iter_reference_t<_Iter>>
 	&& same_as<remove_cvref_t<iter_reference_t<_Iter>>,
 		   typename indirectly_readable_traits<_Iter>::value_type>
 	&& requires(_Iter __it)
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index f0d81cbea0c..941189d65c3 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -1892,7 +1892,9 @@  namespace views::__adaptor
 	    using _Fpc = __detail::__maybe_const_t<_Const, _Fp>;
 	    using _Base = transform_view::_Base<_Const>;
 	    using _Res = invoke_result_t<_Fpc&, range_reference_t<_Base>>;
-	    if constexpr (is_lvalue_reference_v<_Res>)
+	    // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	    // 3798. Rvalue reference and iterator_category
+	    if constexpr (is_reference_v<_Res>)
 	      {
 		using _Cat
 		  = typename iterator_traits<iterator_t<_Base>>::iterator_category;
@@ -5047,7 +5049,9 @@  namespace views::__adaptor
 	  using __detail::__range_iter_cat;
 	  using _Res = invoke_result_t<__maybe_const_t<_Const, _Fp>&,
 				       range_reference_t<__maybe_const_t<_Const, _Vs>>...>;
-	  if constexpr (!is_lvalue_reference_v<_Res>)
+	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	  // 3798. Rvalue reference and iterator_category
+	  if constexpr (!is_reference_v<_Res>)
 	    return input_iterator_tag{};
 	  else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>,
 					   random_access_iterator_tag> && ...))
@@ -5820,7 +5824,9 @@  namespace views::__adaptor
       using _Res = invoke_result_t<__unarize<__maybe_const_t<_Const, _Fp>&, _Nm>,
 				   range_reference_t<_Base>>;
       using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category;
-      if constexpr (!is_lvalue_reference_v<_Res>)
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 3798. Rvalue reference and iterator_category
+      if constexpr (!is_reference_v<_Res>)
 	return input_iterator_tag{};
       else if constexpr (derived_from<_Cat, random_access_iterator_tag>)
 	return random_access_iterator_tag{};
@@ -7228,7 +7234,9 @@  namespace views::__adaptor
 	  using _OuterCat = typename iterator_traits<_OuterIter>::iterator_category;
 	  using _InnerCat = typename iterator_traits<_InnerIter>::iterator_category;
 	  using _PatternCat = typename iterator_traits<_PatternIter>::iterator_category;
-	  if constexpr (!is_lvalue_reference_v<common_reference_t<iter_reference_t<_InnerIter>,
+	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	  // 3798. Rvalue reference and iterator_category
+	  if constexpr (!is_reference_v<common_reference_t<iter_reference_t<_InnerIter>,
 								  iter_reference_t<_PatternIter>>>)
 	    return input_iterator_tag{};
 	  else if constexpr (derived_from<_OuterCat, bidirectional_iterator_tag>
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
index ca695349650..e1b74353e63 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
@@ -214,6 +214,21 @@  test10()
   static_assert(std::same_as<cat, std::random_access_iterator_tag>);
 }
 
+void
+test11()
+{
+  struct MoveIt {
+    int&& operator()(int& i) const { return std::move(i); }
+  };
+
+  int x[] {2, 4};
+  auto xform = x | views::transform(MoveIt{});
+  using iterator = decltype(xform.begin());
+  // LWG 3798. Rvalue reference and iterator_category
+  using cat = std::iterator_traits<iterator>::iterator_category;
+  static_assert(std::same_as<cat, std::random_access_iterator_tag>);
+}
+
 int
 main()
 {
@@ -227,4 +242,5 @@  main()
   test08();
   test09();
   test10();
+  test11();
 }