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 >