diff mbox series

libstdc++: Implement LWG 3664 changes to ranges::distance

Message ID 20241004183404.218709-1-ppalka@redhat.com
State New
Headers show
Series libstdc++: Implement LWG 3664 changes to ranges::distance | expand

Commit Message

Patrick Palka Oct. 4, 2024, 6:34 p.m. UTC
Tested on x86_64-pc-linux-gnu, does this look OK for trunk/backports?

-- >8 --

libstdc++-v3/ChangeLog:

	* include/bits/ranges_base.h (__distance_fn::operator()):
	Adjust iterator/sentinel overloads as per LWG 3664.
	* testsuite/24_iterators/range_operations/distance.cc:
	Test LWG 3664 example.
---
 libstdc++-v3/include/bits/ranges_base.h            | 14 +++++++-------
 .../24_iterators/range_operations/distance.cc      | 11 +++++++++++
 2 files changed, 18 insertions(+), 7 deletions(-)

Comments

Jonathan Wakely Oct. 4, 2024, 6:52 p.m. UTC | #1
On Fri, 4 Oct 2024 at 19:37, Patrick Palka <ppalka@redhat.com> wrote:
>
> Tested on x86_64-pc-linux-gnu, does this look OK for trunk/backports?

OK for all branches (assuming we already have LWG 3392 on the branches).


>
> -- >8 --
>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/ranges_base.h (__distance_fn::operator()):
>         Adjust iterator/sentinel overloads as per LWG 3664.
>         * testsuite/24_iterators/range_operations/distance.cc:
>         Test LWG 3664 example.
> ---
>  libstdc++-v3/include/bits/ranges_base.h            | 14 +++++++-------
>  .../24_iterators/range_operations/distance.cc      | 11 +++++++++++
>  2 files changed, 18 insertions(+), 7 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h
> index 137c3c98e14..cb2eba1f841 100644
> --- a/libstdc++-v3/include/bits/ranges_base.h
> +++ b/libstdc++-v3/include/bits/ranges_base.h
> @@ -947,7 +947,9 @@ namespace ranges
>
>    struct __distance_fn final
>    {
> -    template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
> +    // _GLIBCXX_RESOLVE_LIB_DEFECTS
> +    // 3664. LWG 3392 broke std::ranges::distance(a, a+3)
> +    template<typename _It, sentinel_for<_It> _Sent>
>        requires (!sized_sentinel_for<_Sent, _It>)
>        constexpr iter_difference_t<_It>
>        operator()[[nodiscard]](_It __first, _Sent __last) const
> @@ -961,13 +963,11 @@ namespace ranges
>         return __n;
>        }
>
> -    template<input_or_output_iterator _It, sized_sentinel_for<_It> _Sent>
> +    template<typename _It, sized_sentinel_for<decay_t<_It>> _Sent>
>        [[nodiscard]]
> -      constexpr iter_difference_t<_It>
> -      operator()(const _It& __first, const _Sent& __last) const
> -      {
> -       return __last - __first;
> -      }
> +      constexpr iter_difference_t<decay_t<_It>>
> +      operator()(_It&& __first, _Sent __last) const
> +      { return __last - static_cast<const decay_t<_It>&>(__first); }
>
>      template<range _Range>
>        [[nodiscard]]
> diff --git a/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc b/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
> index 9a1d0c3efe8..336956936c2 100644
> --- a/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
> +++ b/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
> @@ -144,6 +144,16 @@ test05()
>    VERIFY( std::ranges::distance(c4) == 5 );
>  }
>
> +void
> +test06()
> +{
> +  // LWG 3664 - LWG 3392 broke std::ranges::distance(a, a+3)
> +  int a[] = {1, 2, 3};
> +  VERIFY( std::ranges::distance(a, a+3) == 3 );
> +  VERIFY( std::ranges::distance(a, a) == 0 );
> +  VERIFY( std::ranges::distance(a+3, a) == -3 );
> +}
> +
>  int
>  main()
>  {
> @@ -152,4 +162,5 @@ main()
>    test03();
>    test04();
>    test05();
> +  test06();
>  }
> --
> 2.47.0.rc1
>
diff mbox series

Patch

diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h
index 137c3c98e14..cb2eba1f841 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -947,7 +947,9 @@  namespace ranges
 
   struct __distance_fn final
   {
-    template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+    // _GLIBCXX_RESOLVE_LIB_DEFECTS
+    // 3664. LWG 3392 broke std::ranges::distance(a, a+3)
+    template<typename _It, sentinel_for<_It> _Sent>
       requires (!sized_sentinel_for<_Sent, _It>)
       constexpr iter_difference_t<_It>
       operator()[[nodiscard]](_It __first, _Sent __last) const
@@ -961,13 +963,11 @@  namespace ranges
 	return __n;
       }
 
-    template<input_or_output_iterator _It, sized_sentinel_for<_It> _Sent>
+    template<typename _It, sized_sentinel_for<decay_t<_It>> _Sent>
       [[nodiscard]]
-      constexpr iter_difference_t<_It>
-      operator()(const _It& __first, const _Sent& __last) const
-      {
-	return __last - __first;
-      }
+      constexpr iter_difference_t<decay_t<_It>>
+      operator()(_It&& __first, _Sent __last) const
+      { return __last - static_cast<const decay_t<_It>&>(__first); }
 
     template<range _Range>
       [[nodiscard]]
diff --git a/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc b/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
index 9a1d0c3efe8..336956936c2 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
@@ -144,6 +144,16 @@  test05()
   VERIFY( std::ranges::distance(c4) == 5 );
 }
 
+void
+test06()
+{
+  // LWG 3664 - LWG 3392 broke std::ranges::distance(a, a+3)
+  int a[] = {1, 2, 3};
+  VERIFY( std::ranges::distance(a, a+3) == 3 );
+  VERIFY( std::ranges::distance(a, a) == 0 );
+  VERIFY( std::ranges::distance(a+3, a) == -3 );
+}
+
 int
 main()
 {
@@ -152,4 +162,5 @@  main()
   test03();
   test04();
   test05();
+  test06();
 }