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>;
&& is_nothrow_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
{
&& is_nothrow_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
{
&& is_nothrow_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
&& is_nothrow_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
void
test_pr101587()
{
- short in[1];
+ 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());
+
+ // iterator that has an integer-like class type for difference_type
+ struct Iter
+ {
+ using value_type = long;
+ using difference_type = std::ranges::__detail::__max_diff_type;
+
+ long& operator*() const { return *p; }
+
+ Iter& operator++() { ++p; return *this; }
+ Iter operator++(int) { return Iter{p++}; }
+
+ difference_type operator-(Iter i) const { return p - i.p; }
+ bool operator==(const Iter&) const = default;
+
+ long* p = nullptr;
+ };
+ static_assert(std::sized_sentinel_for<Iter, Iter>);
+
+ std::ranges::subrange<Iter> rmax(Iter{out+0}, Iter{out+1});
+ // Check with integer-like class type for output range:
+ std::ranges::uninitialized_copy(in, rmax);
+ std::ranges::uninitialized_copy_n(in+0, 1, rmax.begin(), rmax.end());
+
+ int to[1];
+ // And for input range:
+ std::ranges::uninitialized_copy(rmax, to);
+ std::ranges::uninitialized_copy_n(rmax.begin(), 1, to+0, to+1);
}
int
void
test_pr101587()
{
- short in[1];
+ 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());
+
+ struct Iter
+ {
+ using value_type = long;
+ using difference_type = std::ranges::__detail::__max_diff_type;
+
+ long& operator*() const { return *p; }
+
+ Iter& operator++() { ++p; return *this; }
+ Iter operator++(int) { return Iter{p++}; }
+
+ difference_type operator-(Iter i) const { return p - i.p; }
+ bool operator==(const Iter&) const = default;
+
+ long* p = nullptr;
+ };
+ static_assert(std::sized_sentinel_for<Iter, Iter>);
+
+ std::ranges::subrange<Iter> rmax(Iter{out+0}, Iter{out+1});
+ // Check with integer-like class type for output range:
+ std::ranges::uninitialized_move(in, rmax);
+ std::ranges::uninitialized_move_n(in+0, 1, rmax.begin(), rmax.end());
+
+ int to[1];
+ // And for input range:
+ std::ranges::uninitialized_copy(rmax, to);
+ std::ranges::uninitialized_copy_n(rmax.begin(), 1, to+0, to+1);
}
int