On Wed, 26 Mar 2025 at 11:50, Jonathan Wakely <jwak...@redhat.com> wrote:
>
> Because ranges can have any signed integer-like type as difference_type,
> it's not valid to use std::min(diff1, diff2). Instead of calling
> std::min with an explicit template argument, this adds a new __min
> helper that determines the common type and uses that with std::min.
>
> libstdc++-v3/ChangeLog:
>
>         PR libstdc++/101587
>         * include/bits/ranges_uninitialized.h (__detail::__min): New
>         function object.
>         (ranges::uninitialized_copy, ranges::uninitialized_copy_n)
>         (ranges::uninitialized_move, ranges::uninitialized_move_n): Use
>         __min instead of std::min.
>         * 
> testsuite/20_util/specialized_algorithms/uninitialized_copy/constrained.cc:
>         Check ranges with difference difference types.
>         * 
> testsuite/20_util/specialized_algorithms/uninitialized_move/constrained.cc:
>         Likewise.
> ---
>
> Tested x86_64-linux.
>
>  .../include/bits/ranges_uninitialized.h       | 32 +++++++++++++++----
>  .../uninitialized_copy/constrained.cc         | 13 ++++++++
>  .../uninitialized_move/constrained.cc         | 13 ++++++++
>  3 files changed, 52 insertions(+), 6 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/ranges_uninitialized.h 
> b/libstdc++-v3/include/bits/ranges_uninitialized.h
> index 990929efaa9..92a45e8fcff 100644
> --- a/libstdc++-v3/include/bits/ranges_uninitialized.h
> +++ b/libstdc++-v3/include/bits/ranges_uninitialized.h
> @@ -263,6 +263,26 @@ namespace ranges
>    inline constexpr __uninitialized_value_construct_n_fn
>      uninitialized_value_construct_n;
>
> +  namespace __detail
> +  {
> +    // This is only intended for finding smaller iterator differences below,
> +    // not as a general purpose replacement for std::min.
> +    struct __min_fn
> +    {
> +      template<typename _Dp1, typename _Dp2>
> +       common_type_t<_Dp1, _Dp2>

This needs to be constexpr.

> +       operator()(_Dp1 __d1, _Dp2 __d2) const noexcept
> +       {
> +         // Every C++20 iterator I satisfies weakly_incrementable<I> which
> +         // requires signed-integer-like<iter_difference_t<I>>.
> +         static_assert(std::__detail::__is_signed_integer_like<_Dp1>);
> +         static_assert(std::__detail::__is_signed_integer_like<_Dp2>);
> +         return std::min<common_type_t<_Dp1, _Dp2>>(__d1, __d2);
> +       }
> +    };
> +    inline constexpr __min_fn __min{};
> +  }
> +
>    template<typename _Iter, typename _Out>
>      using uninitialized_copy_result = in_out_result<_Iter, _Out>;
>
> @@ -287,8 +307,8 @@ namespace ranges
>           {
>             auto __d1 = __ilast - __ifirst;
>             auto __d2 = __olast - __ofirst;
> -           return ranges::copy_n(std::move(__ifirst), std::min(__d1, __d2),
> -                                 __ofirst);
> +           return ranges::copy_n(std::move(__ifirst),
> +                                 __detail::__min(__d1, __d2), __ofirst);
>           }
>         else
>           {
> @@ -337,8 +357,8 @@ namespace ranges
>                                                  iter_reference_t<_Iter>>)
>           {
>             auto __d = __olast - __ofirst;
> -           return ranges::copy_n(std::move(__ifirst), std::min(__n, __d),
> -                                 __ofirst);
> +           return ranges::copy_n(std::move(__ifirst),
> +                                 __detail::__min(__n, __d), __ofirst);
>           }
>         else
>           {
> @@ -381,7 +401,7 @@ namespace ranges
>             auto __d2 = __olast - __ofirst;
>             auto [__in, __out]
>               = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)),
> -                              std::min(__d1, __d2), __ofirst);
> +                              __detail::__min(__d1, __d2), __ofirst);
>             return {std::move(__in).base(), __out};
>           }
>         else
> @@ -435,7 +455,7 @@ namespace ranges
>             auto __d = __olast - __ofirst;
>             auto [__in, __out]
>               = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)),
> -                              std::min(__n, __d), __ofirst);
> +                              __detail::__min(__n, __d), __ofirst);
>             return {std::move(__in).base(), __out};
>           }
>         else
> diff --git 
> a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constrained.cc
>  
> b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constrained.cc
> index e0589e33f3d..af3b73364ec 100644
> --- 
> a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constrained.cc
> +++ 
> b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constrained.cc
> @@ -175,6 +175,17 @@ test03()
>      }
>  }
>
> +void
> +test_pr101587()
> +{
> +  short in[1];
> +  __gnu_test::test_contiguous_range r(in); // difference_type is integer-like
> +  long out[1];
> +  std::span<long> o(out); // difference_type is ptrdiff_t
> +  ranges::uninitialized_copy(r, o);
> +  ranges::uninitialized_copy_n(ranges::begin(r), 0, o.begin(), o.end());
> +}
> +
>  int
>  main()
>  {
> @@ -188,4 +199,6 @@ main()
>
>    test02<false>();
>    test02<true>();
> +
> +  test_pr101587();
>  }
> diff --git 
> a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constrained.cc
>  
> b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constrained.cc
> index 4c858e13704..fe82d1f156e 100644
> --- 
> a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constrained.cc
> +++ 
> b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constrained.cc
> @@ -185,6 +185,17 @@ test03()
>      }
>  }
>
> +void
> +test_pr101587()
> +{
> +  short in[1];
> +  __gnu_test::test_contiguous_range r(in); // difference_type is integer-like
> +  long out[1];
> +  std::span<long> o(out); // difference_type is ptrdiff_t
> +  ranges::uninitialized_move(r, o);
> +  ranges::uninitialized_move_n(ranges::begin(r), 0, o.begin(), o.end());
> +}
> +
>  int
>  main()
>  {
> @@ -198,4 +209,6 @@ main()
>
>    test02<false>();
>    test02<true>();
> +
> +  test_pr101587();
>  }
> --
> 2.49.0
>

Reply via email to