On Fri, Apr 4, 2025 at 11:10 AM Jonathan Wakely <[email protected]> wrote:
> In r15-8980-gf4b6acfc36fb1f I introduced a new function object for
> finding the smaller of two distances. In bugzilla Hewill Kang pointed
> out that we still need to explicitly convert the result back to the
> right difference type, because the result might be an integer-like class
> type that doesn't convert to an integral type explicitly.
>
> Rather than doing that conversion in the __mindist function object, I
> think it's simpler to remove it again and just do a comparison and
> assignment. We always want the result to have a specific type, so we can
> just check if the value of the other type is smaller, and then convert
> that to the other type if so.
>
> libstdc++-v3/ChangeLog:
>
> PR libstdc++/101587
> * include/bits/ranges_uninitialized.h (__detail::__mindist):
> Remove.
> (ranges::uninitialized_copy, ranges::uninitialized_copy_n)
> (ranges::uninitialized_move, ranges::uninitialized_move_n): Use
> comparison and assignment instead of __mindist.
> ---
>
> Tested x86_64-linux.
>
The revert makes sense, but this integer-like-classes are causing a lot of
churm.
I would like to see some tests for this scenario in algorithms tests.
Using iota<__int128>(0, 5) is good way to produce integer-like difference
type,
that is sized. (iota<__int128>(0) | views::take(5)) creates not-sized one.
With test LGTM.
>
> .../include/bits/ranges_uninitialized.h | 46 ++++++-------------
> 1 file changed, 14 insertions(+), 32 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/ranges_uninitialized.h
> b/libstdc++-v3/include/bits/ranges_uninitialized.h
> index b5580073a6a..12a714b68aa 100644
> --- a/libstdc++-v3/include/bits/ranges_uninitialized.h
> +++ b/libstdc++-v3/include/bits/ranges_uninitialized.h
> @@ -263,26 +263,6 @@ 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>;
>
> @@ -305,10 +285,10 @@ namespace ranges
> && is_trivially_assignable_v<_OutType&,
> iter_reference_t<_Iter>>)
> {
> - auto __d1 = __ilast - __ifirst;
> - auto __d2 = __olast - __ofirst;
> - return ranges::copy_n(std::move(__ifirst),
> - __detail::__mindist(__d1, __d2),
> __ofirst);
> + auto __d = __ilast - __ifirst;
> + if (auto __d2 = __olast - __ofirst; __d2 < __d)
> + __d = static_cast<iter_difference_t<_Iter>>(__d2);
> + return ranges::copy_n(std::move(__ifirst), __d, __ofirst);
> }
> else
> {
> @@ -356,9 +336,9 @@ namespace ranges
> && is_trivially_assignable_v<_OutType&,
> iter_reference_t<_Iter>>)
> {
> - auto __d = __olast - __ofirst;
> - return ranges::copy_n(std::move(__ifirst),
> - __detail::__mindist(__n, __d), __ofirst);
> + if (auto __d = __olast - __ofirst; __d < __n)
> + __n = static_cast<iter_difference_t<_Iter>>(__d);
> + return ranges::copy_n(std::move(__ifirst), __n, __ofirst);
> }
> else
> {
> @@ -397,11 +377,12 @@ namespace ranges
> && is_trivially_assignable_v<_OutType&,
>
> iter_rvalue_reference_t<_Iter>>)
> {
> - auto __d1 = __ilast - __ifirst;
> - auto __d2 = __olast - __ofirst;
> + auto __d = __ilast - __ifirst;
> + if (auto __d2 = __olast - __ofirst; __d2 < __d)
> + __d = static_cast<iter_difference_t<_Iter>>(__d2);
> auto [__in, __out]
> =
> ranges::copy_n(std::make_move_iterator(std::move(__ifirst)),
> - __detail::__mindist(__d1, __d2), __ofirst);
> + __d, __ofirst);
> return {std::move(__in).base(), __out};
> }
> else
> @@ -452,10 +433,11 @@ namespace ranges
> && is_trivially_assignable_v<_OutType&,
>
> iter_rvalue_reference_t<_Iter>>)
> {
> - auto __d = __olast - __ofirst;
> + if (auto __d = __olast - __ofirst; __d < __n)
> + __n = static_cast<iter_difference_t<_Iter>>(__d);
> auto [__in, __out]
> =
> ranges::copy_n(std::make_move_iterator(std::move(__ifirst)),
> - __detail::__mindist(__n, __d), __ofirst);
> + __n, __ofirst);
> return {std::move(__in).base(), __out};
> }
> else
> --
> 2.49.0
>
>