diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2025-03-26 11:47:05 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2025-03-27 15:26:32 +0000 |
commit | f4b6acfc36fb1f72fdd5bf4da208515e6495a062 (patch) | |
tree | 444e269f1ac25354746f1b42fa52f08418f5fcd9 | |
parent | 16766d5a0c4a946d3ba9255a99621975b9773e18 (diff) | |
download | gcc-f4b6acfc36fb1f72fdd5bf4da208515e6495a062.zip gcc-f4b6acfc36fb1f72fdd5bf4da208515e6495a062.tar.gz gcc-f4b6acfc36fb1f72fdd5bf4da208515e6495a062.tar.bz2 |
libstdc++: Replace use of std::min in ranges::uninitialized_xxx algos [PR101587]
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 __mindist
helper that determines the common type and uses that with std::min.
libstdc++-v3/ChangeLog:
PR libstdc++/101587
* include/bits/ranges_uninitialized.h (__detail::__mindist):
New function object.
(ranges::uninitialized_copy, ranges::uninitialized_copy_n)
(ranges::uninitialized_move, ranges::uninitialized_move_n): Use
__mindist 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.
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 990929e..b558007 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 __mindist_fn + { + template<typename _Dp1, typename _Dp2> + constexpr common_type_t<_Dp1, _Dp2> + 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 __mindist_fn __mindist{}; + } + 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::__mindist(__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::__mindist(__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::__mindist(__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::__mindist(__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 e0589e3..af3b733 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 4c858e1..fe82d1f1 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(); } |