And iota<__int128>(0) | views::take(5) | views::transform([&v](auto i) -> auto& { return v[i]; }) to create output range particularly for this case, I think?
Tomasz Kaminski <tkami...@redhat.com>於 2025年4月4日 週五,17:31寫道: > > > On Fri, Apr 4, 2025 at 11:10 AM Jonathan Wakely <jwak...@redhat.com> > 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 >> >>