mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-22 00:01:10 +08:00
libstdc++: Convert the ranges algorithm entities into function objects
This is the standard way to inhibit ADL for these entities, which is required as per [algorithms.requirements] p2 and [specialized.algorithms] p4. The conversion was done mostly mechanically with a custom Vim macro. libstdc++-v3/ChangeLog: * include/bits/ranges_algo.h: (adjacent_find, all_of, any_of, binary_search, copy_if, count, count_if, equal_range, find, find_end, find_first_of, find_if, find_if_not, for_each, generate, generate_n, includes, inplace_merge, is_heap, is_heap_until, is_partitioned, is_permutation, is_sorted, is_sorted_until, lexicographical_compare, lower_bound, make_heap, max, max_element, merge, min, min_element, minmax, minmax_element, mismatch, next_permutation, none_of, nth_element, partial_sort, partial_sort_copy, partition, partition_copy, partition_point, pop_heap, prev_permutation, push_heap, remove, remove_copy, remove_copy_if, remove_if, replace, replace_copy, replace_copy_if, replace_if, reverse, reverse_copy, rotate, rotate_copy, search, search_n, set_difference, set_intersection, set_symmetric_difference, set_union, shuffle, sort, sort_heap, stable_partition, stable_sort, swap_ranges, transform, unique, unique_copy, upper_bound): Convert into function objects. * include/bits/ranges_algobase.h: (equal, copy, move, copy_n, fill_n, fill, move_backward, copy_backward): Likewise. * include/bits/ranges_uninitialized.h (uninitialized_default_construct, uninitialized_default_construct_n, uninitialized_value_construct, uninitialized_value_construct_n, uninitialized_copy, uninitialized_copy_n, uninitialized_move, uninitialized_move_n, uninitialized_fill, uninitialized_fill_n, construct_at, destroy_at, destroy, destroy_n): Likewise.
This commit is contained in:
parent
90b7eb6539
commit
b40c57bdd2
@ -1,5 +1,29 @@
|
||||
2020-02-15 Patrick Palka <ppalka@redhat.com>
|
||||
|
||||
* include/bits/ranges_algo.h: (adjacent_find, all_of, any_of,
|
||||
binary_search, copy_if, count, count_if, equal_range, find, find_end,
|
||||
find_first_of, find_if, find_if_not, for_each, generate, generate_n,
|
||||
includes, inplace_merge, is_heap, is_heap_until, is_partitioned,
|
||||
is_permutation, is_sorted, is_sorted_until, lexicographical_compare,
|
||||
lower_bound, make_heap, max, max_element, merge, min, min_element,
|
||||
minmax, minmax_element, mismatch, next_permutation, none_of,
|
||||
nth_element, partial_sort, partial_sort_copy, partition, partition_copy,
|
||||
partition_point, pop_heap, prev_permutation, push_heap, remove,
|
||||
remove_copy, remove_copy_if, remove_if, replace, replace_copy,
|
||||
replace_copy_if, replace_if, reverse, reverse_copy, rotate, rotate_copy,
|
||||
search, search_n, set_difference, set_intersection,
|
||||
set_symmetric_difference, set_union, shuffle, sort, sort_heap,
|
||||
stable_partition, stable_sort, swap_ranges, transform, unique,
|
||||
unique_copy, upper_bound): Convert into function objects.
|
||||
* include/bits/ranges_algobase.h: (equal, copy, move, copy_n, fill_n,
|
||||
fill, move_backward, copy_backward): Likewise.
|
||||
* include/bits/ranges_uninitialized.h (uninitialized_default_construct,
|
||||
uninitialized_default_construct_n, uninitialized_value_construct,
|
||||
uninitialized_value_construct_n, uninitialized_copy,
|
||||
uninitialized_copy_n, uninitialized_move, uninitialized_move_n,
|
||||
uninitialized_fill, uninitialized_fill_n, construct_at, destroy_at,
|
||||
destroy, destroy_n): Likewise.
|
||||
|
||||
* include/bits/ranges_algo.h (ranges::__find_end): Fold into ...
|
||||
(ranges::find_end): ... here.
|
||||
(ranges::__lexicographical_compare): Fold into ...
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -71,88 +71,93 @@ namespace ranges
|
||||
__is_move_iterator<move_iterator<_Iterator>> = true;
|
||||
} // namespace __detail
|
||||
|
||||
template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
|
||||
input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
|
||||
typename _Pred = ranges::equal_to,
|
||||
typename _Proj1 = identity, typename _Proj2 = identity>
|
||||
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
|
||||
constexpr bool
|
||||
equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
|
||||
_Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
|
||||
{
|
||||
// TODO: implement more specializations to at least have parity with
|
||||
// std::equal.
|
||||
if constexpr (__detail::__is_normal_iterator<_Iter1>
|
||||
|| __detail::__is_normal_iterator<_Iter2>)
|
||||
return ranges::equal(std::__niter_base(std::move(__first1)),
|
||||
std::__niter_base(std::move(__last1)),
|
||||
std::__niter_base(std::move(__first2)),
|
||||
std::__niter_base(std::move(__last2)),
|
||||
struct __equal_fn
|
||||
{
|
||||
template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
|
||||
input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
|
||||
typename _Pred = ranges::equal_to,
|
||||
typename _Proj1 = identity, typename _Proj2 = identity>
|
||||
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
|
||||
constexpr bool
|
||||
operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
|
||||
_Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
|
||||
{
|
||||
// TODO: implement more specializations to at least have parity with
|
||||
// std::equal.
|
||||
if constexpr (__detail::__is_normal_iterator<_Iter1>
|
||||
|| __detail::__is_normal_iterator<_Iter2>)
|
||||
return (*this)(std::__niter_base(std::move(__first1)),
|
||||
std::__niter_base(std::move(__last1)),
|
||||
std::__niter_base(std::move(__first2)),
|
||||
std::__niter_base(std::move(__last2)),
|
||||
std::move(__pred),
|
||||
std::move(__proj1), std::move(__proj2));
|
||||
|
||||
constexpr bool __sized_iters
|
||||
= (sized_sentinel_for<_Sent1, _Iter1>
|
||||
&& sized_sentinel_for<_Sent2, _Iter2>);
|
||||
if constexpr (__sized_iters)
|
||||
{
|
||||
auto __d1 = ranges::distance(__first1, __last1);
|
||||
auto __d2 = ranges::distance(__first2, __last2);
|
||||
if (__d1 != __d2)
|
||||
return false;
|
||||
|
||||
using _ValueType1 = iter_value_t<_Iter1>;
|
||||
using _ValueType2 = iter_value_t<_Iter2>;
|
||||
constexpr bool __use_memcmp
|
||||
= ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>)
|
||||
&& is_same_v<_ValueType1, _ValueType2>
|
||||
&& is_pointer_v<_Iter1>
|
||||
&& is_pointer_v<_Iter2>
|
||||
&& is_same_v<_Pred, ranges::equal_to>
|
||||
&& is_same_v<_Proj1, identity>
|
||||
&& is_same_v<_Proj2, identity>);
|
||||
if constexpr (__use_memcmp)
|
||||
{
|
||||
if (const size_t __len = (__last1 - __first1))
|
||||
return !std::__memcmp(__first1, __first2, __len);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; __first1 != __last1; ++__first1, (void)++__first2)
|
||||
if (!(bool)std::__invoke(__pred,
|
||||
std::__invoke(__proj1, *__first1),
|
||||
std::__invoke(__proj2, *__first2)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; __first1 != __last1 && __first2 != __last2;
|
||||
++__first1, (void)++__first2)
|
||||
if (!(bool)std::__invoke(__pred,
|
||||
std::__invoke(__proj1, *__first1),
|
||||
std::__invoke(__proj2, *__first2)))
|
||||
return false;
|
||||
return __first1 == __last1 && __first2 == __last2;
|
||||
}
|
||||
}
|
||||
|
||||
template<input_range _Range1, input_range _Range2,
|
||||
typename _Pred = ranges::equal_to,
|
||||
typename _Proj1 = identity, typename _Proj2 = identity>
|
||||
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
|
||||
_Pred, _Proj1, _Proj2>
|
||||
constexpr bool
|
||||
operator()(_Range1&& __r1, _Range2&& __r2,
|
||||
_Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
|
||||
{
|
||||
return (*this)(ranges::begin(__r1), ranges::end(__r1),
|
||||
ranges::begin(__r2), ranges::end(__r2),
|
||||
std::move(__pred),
|
||||
std::move(__proj1), std::move(__proj2));
|
||||
}
|
||||
};
|
||||
|
||||
constexpr bool __sized_iters
|
||||
= (sized_sentinel_for<_Sent1, _Iter1>
|
||||
&& sized_sentinel_for<_Sent2, _Iter2>);
|
||||
if constexpr (__sized_iters)
|
||||
{
|
||||
auto __d1 = ranges::distance(__first1, __last1);
|
||||
auto __d2 = ranges::distance(__first2, __last2);
|
||||
if (__d1 != __d2)
|
||||
return false;
|
||||
|
||||
using _ValueType1 = iter_value_t<_Iter1>;
|
||||
using _ValueType2 = iter_value_t<_Iter2>;
|
||||
constexpr bool __use_memcmp
|
||||
= ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>)
|
||||
&& is_same_v<_ValueType1, _ValueType2>
|
||||
&& is_pointer_v<_Iter1>
|
||||
&& is_pointer_v<_Iter2>
|
||||
&& is_same_v<_Pred, ranges::equal_to>
|
||||
&& is_same_v<_Proj1, identity>
|
||||
&& is_same_v<_Proj2, identity>);
|
||||
if constexpr (__use_memcmp)
|
||||
{
|
||||
if (const size_t __len = (__last1 - __first1))
|
||||
return !std::__memcmp(__first1, __first2, __len);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; __first1 != __last1; ++__first1, (void)++__first2)
|
||||
if (!(bool)std::__invoke(__pred,
|
||||
std::__invoke(__proj1, *__first1),
|
||||
std::__invoke(__proj2, *__first2)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; __first1 != __last1 && __first2 != __last2;
|
||||
++__first1, (void)++__first2)
|
||||
if (!(bool)std::__invoke(__pred,
|
||||
std::__invoke(__proj1, *__first1),
|
||||
std::__invoke(__proj2, *__first2)))
|
||||
return false;
|
||||
return __first1 == __last1 && __first2 == __last2;
|
||||
}
|
||||
}
|
||||
|
||||
template<input_range _Range1, input_range _Range2,
|
||||
typename _Pred = ranges::equal_to,
|
||||
typename _Proj1 = identity, typename _Proj2 = identity>
|
||||
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>,
|
||||
_Pred, _Proj1, _Proj2>
|
||||
constexpr bool
|
||||
equal(_Range1&& __r1, _Range2&& __r2,
|
||||
_Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
|
||||
{
|
||||
return ranges::equal(ranges::begin(__r1), ranges::end(__r1),
|
||||
ranges::begin(__r2), ranges::end(__r2),
|
||||
std::move(__pred),
|
||||
std::move(__proj1), std::move(__proj2));
|
||||
}
|
||||
inline constexpr __equal_fn equal{};
|
||||
|
||||
template<typename _Iter, typename _Out>
|
||||
struct copy_result
|
||||
@ -288,45 +293,55 @@ namespace ranges
|
||||
}
|
||||
}
|
||||
|
||||
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
|
||||
weakly_incrementable _Out>
|
||||
requires indirectly_copyable<_Iter, _Out>
|
||||
constexpr copy_result<_Iter, _Out>
|
||||
copy(_Iter __first, _Sent __last, _Out __result)
|
||||
{
|
||||
return ranges::__copy_or_move<false>(std::move(__first),
|
||||
std::move(__last),
|
||||
std::move(__result));
|
||||
}
|
||||
struct __copy_fn
|
||||
{
|
||||
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
|
||||
weakly_incrementable _Out>
|
||||
requires indirectly_copyable<_Iter, _Out>
|
||||
constexpr copy_result<_Iter, _Out>
|
||||
operator()(_Iter __first, _Sent __last, _Out __result) const
|
||||
{
|
||||
return ranges::__copy_or_move<false>(std::move(__first),
|
||||
std::move(__last),
|
||||
std::move(__result));
|
||||
}
|
||||
|
||||
template<input_range _Range, weakly_incrementable _Out>
|
||||
requires indirectly_copyable<iterator_t<_Range>, _Out>
|
||||
constexpr copy_result<safe_iterator_t<_Range>, _Out>
|
||||
copy(_Range&& __r, _Out __result)
|
||||
{
|
||||
return ranges::copy(ranges::begin(__r), ranges::end(__r),
|
||||
std::move(__result));
|
||||
}
|
||||
template<input_range _Range, weakly_incrementable _Out>
|
||||
requires indirectly_copyable<iterator_t<_Range>, _Out>
|
||||
constexpr copy_result<safe_iterator_t<_Range>, _Out>
|
||||
operator()(_Range&& __r, _Out __result) const
|
||||
{
|
||||
return (*this)(ranges::begin(__r), ranges::end(__r),
|
||||
std::move(__result));
|
||||
}
|
||||
};
|
||||
|
||||
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
|
||||
weakly_incrementable _Out>
|
||||
requires indirectly_movable<_Iter, _Out>
|
||||
constexpr move_result<_Iter, _Out>
|
||||
move(_Iter __first, _Sent __last, _Out __result)
|
||||
{
|
||||
return ranges::__copy_or_move<true>(std::move(__first),
|
||||
std::move(__last),
|
||||
std::move(__result));
|
||||
}
|
||||
inline constexpr __copy_fn copy{};
|
||||
|
||||
template<input_range _Range, weakly_incrementable _Out>
|
||||
requires indirectly_movable<iterator_t<_Range>, _Out>
|
||||
constexpr move_result<safe_iterator_t<_Range>, _Out>
|
||||
move(_Range&& __r, _Out __result)
|
||||
{
|
||||
return ranges::move(ranges::begin(__r), ranges::end(__r),
|
||||
std::move(__result));
|
||||
}
|
||||
struct __move_fn
|
||||
{
|
||||
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
|
||||
weakly_incrementable _Out>
|
||||
requires indirectly_movable<_Iter, _Out>
|
||||
constexpr move_result<_Iter, _Out>
|
||||
operator()(_Iter __first, _Sent __last, _Out __result) const
|
||||
{
|
||||
return ranges::__copy_or_move<true>(std::move(__first),
|
||||
std::move(__last),
|
||||
std::move(__result));
|
||||
}
|
||||
|
||||
template<input_range _Range, weakly_incrementable _Out>
|
||||
requires indirectly_movable<iterator_t<_Range>, _Out>
|
||||
constexpr move_result<safe_iterator_t<_Range>, _Out>
|
||||
operator()(_Range&& __r, _Out __result) const
|
||||
{
|
||||
return (*this)(ranges::begin(__r), ranges::end(__r),
|
||||
std::move(__result));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __move_fn move{};
|
||||
|
||||
template<bool _IsMove,
|
||||
bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
|
||||
@ -420,127 +435,152 @@ namespace ranges
|
||||
}
|
||||
}
|
||||
|
||||
template<bidirectional_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
|
||||
bidirectional_iterator _Iter2>
|
||||
requires indirectly_copyable<_Iter1, _Iter2>
|
||||
constexpr copy_backward_result<_Iter1, _Iter2>
|
||||
copy_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result)
|
||||
{
|
||||
return ranges::__copy_or_move_backward<false>(std::move(__first),
|
||||
std::move(__last),
|
||||
std::move(__result));
|
||||
}
|
||||
struct __copy_backward_fn
|
||||
{
|
||||
template<bidirectional_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
|
||||
bidirectional_iterator _Iter2>
|
||||
requires indirectly_copyable<_Iter1, _Iter2>
|
||||
constexpr copy_backward_result<_Iter1, _Iter2>
|
||||
operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const
|
||||
{
|
||||
return ranges::__copy_or_move_backward<false>(std::move(__first),
|
||||
std::move(__last),
|
||||
std::move(__result));
|
||||
}
|
||||
|
||||
template<bidirectional_range _Range, bidirectional_iterator _Iter>
|
||||
requires indirectly_copyable<iterator_t<_Range>, _Iter>
|
||||
constexpr copy_backward_result<safe_iterator_t<_Range>, _Iter>
|
||||
copy_backward(_Range&& __r, _Iter __result)
|
||||
{
|
||||
return ranges::copy_backward(ranges::begin(__r), ranges::end(__r),
|
||||
std::move(__result));
|
||||
}
|
||||
template<bidirectional_range _Range, bidirectional_iterator _Iter>
|
||||
requires indirectly_copyable<iterator_t<_Range>, _Iter>
|
||||
constexpr copy_backward_result<safe_iterator_t<_Range>, _Iter>
|
||||
operator()(_Range&& __r, _Iter __result) const
|
||||
{
|
||||
return (*this)(ranges::begin(__r), ranges::end(__r),
|
||||
std::move(__result));
|
||||
}
|
||||
};
|
||||
|
||||
template<bidirectional_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
|
||||
bidirectional_iterator _Iter2>
|
||||
requires indirectly_movable<_Iter1, _Iter2>
|
||||
constexpr move_backward_result<_Iter1, _Iter2>
|
||||
move_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result)
|
||||
{
|
||||
return ranges::__copy_or_move_backward<true>(std::move(__first),
|
||||
std::move(__last),
|
||||
std::move(__result));
|
||||
}
|
||||
inline constexpr __copy_backward_fn copy_backward{};
|
||||
|
||||
template<bidirectional_range _Range, bidirectional_iterator _Iter>
|
||||
requires indirectly_movable<iterator_t<_Range>, _Iter>
|
||||
constexpr move_backward_result<safe_iterator_t<_Range>, _Iter>
|
||||
move_backward(_Range&& __r, _Iter __result)
|
||||
{
|
||||
return ranges::move_backward(ranges::begin(__r), ranges::end(__r),
|
||||
std::move(__result));
|
||||
}
|
||||
struct __move_backward_fn
|
||||
{
|
||||
template<bidirectional_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
|
||||
bidirectional_iterator _Iter2>
|
||||
requires indirectly_movable<_Iter1, _Iter2>
|
||||
constexpr move_backward_result<_Iter1, _Iter2>
|
||||
operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const
|
||||
{
|
||||
return ranges::__copy_or_move_backward<true>(std::move(__first),
|
||||
std::move(__last),
|
||||
std::move(__result));
|
||||
}
|
||||
|
||||
template<bidirectional_range _Range, bidirectional_iterator _Iter>
|
||||
requires indirectly_movable<iterator_t<_Range>, _Iter>
|
||||
constexpr move_backward_result<safe_iterator_t<_Range>, _Iter>
|
||||
operator()(_Range&& __r, _Iter __result) const
|
||||
{
|
||||
return (*this)(ranges::begin(__r), ranges::end(__r),
|
||||
std::move(__result));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __move_backward_fn move_backward{};
|
||||
|
||||
template<typename _Iter, typename _Out>
|
||||
using copy_n_result = copy_result<_Iter, _Out>;
|
||||
|
||||
template<input_iterator _Iter, weakly_incrementable _Out>
|
||||
requires indirectly_copyable<_Iter, _Out>
|
||||
constexpr copy_n_result<_Iter, _Out>
|
||||
copy_n(_Iter __first, iter_difference_t<_Iter> __n, _Out __result)
|
||||
{
|
||||
if constexpr (random_access_iterator<_Iter>)
|
||||
return ranges::copy(__first, __first + __n, std::move(__result));
|
||||
else
|
||||
{
|
||||
for (; __n > 0; --__n, (void)++__result, (void)++__first)
|
||||
*__result = *__first;
|
||||
return {std::move(__first), std::move(__result)};
|
||||
}
|
||||
}
|
||||
struct __copy_n_fn
|
||||
{
|
||||
template<input_iterator _Iter, weakly_incrementable _Out>
|
||||
requires indirectly_copyable<_Iter, _Out>
|
||||
constexpr copy_n_result<_Iter, _Out>
|
||||
operator()(_Iter __first, iter_difference_t<_Iter> __n, _Out __result) const
|
||||
{
|
||||
if constexpr (random_access_iterator<_Iter>)
|
||||
return ranges::copy(__first, __first + __n, std::move(__result));
|
||||
else
|
||||
{
|
||||
for (; __n > 0; --__n, (void)++__result, (void)++__first)
|
||||
*__result = *__first;
|
||||
return {std::move(__first), std::move(__result)};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Tp, output_iterator<const _Tp&> _Out>
|
||||
constexpr _Out
|
||||
fill_n(_Out __first, iter_difference_t<_Out> __n, const _Tp& __value)
|
||||
{
|
||||
// TODO: implement more specializations to be at least on par with
|
||||
// std::fill_n
|
||||
if (__n <= 0)
|
||||
return __first;
|
||||
inline constexpr __copy_n_fn copy_n{};
|
||||
|
||||
// TODO: is __is_byte the best condition?
|
||||
if constexpr (is_pointer_v<_Out> && __is_byte<_Tp>::__value)
|
||||
{
|
||||
__builtin_memset(__first, static_cast<unsigned char>(__value), __n);
|
||||
return __first + __n;
|
||||
}
|
||||
else if constexpr (is_scalar_v<_Tp>)
|
||||
{
|
||||
const auto __tmp = __value;
|
||||
for (; __n > 0; --__n, (void)++__first)
|
||||
*__first = __tmp;
|
||||
struct __fill_n_fn
|
||||
{
|
||||
template<typename _Tp, output_iterator<const _Tp&> _Out>
|
||||
constexpr _Out
|
||||
operator()(_Out __first, iter_difference_t<_Out> __n, const _Tp& __value) const
|
||||
{
|
||||
// TODO: implement more specializations to be at least on par with
|
||||
// std::fill_n
|
||||
if (__n <= 0)
|
||||
return __first;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; __n > 0; --__n, (void)++__first)
|
||||
*__first = __value;
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp,
|
||||
output_iterator<const _Tp&> _Out, sentinel_for<_Out> _Sent>
|
||||
constexpr _Out
|
||||
fill(_Out __first, _Sent __last, const _Tp& __value)
|
||||
{
|
||||
// TODO: implement more specializations to be at least on par with
|
||||
// std::fill
|
||||
if constexpr (sized_sentinel_for<_Sent, _Out>)
|
||||
{
|
||||
const auto __len = __last - __first;
|
||||
return ranges::fill_n(__first, __len, __value);
|
||||
}
|
||||
else if constexpr (is_scalar_v<_Tp>)
|
||||
{
|
||||
const auto __tmp = __value;
|
||||
for (; __first != __last; ++__first)
|
||||
*__first = __tmp;
|
||||
return __first;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; __first != __last; ++__first)
|
||||
*__first = __value;
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
// TODO: is __is_byte the best condition?
|
||||
if constexpr (is_pointer_v<_Out> && __is_byte<_Tp>::__value)
|
||||
{
|
||||
__builtin_memset(__first, static_cast<unsigned char>(__value), __n);
|
||||
return __first + __n;
|
||||
}
|
||||
else if constexpr (is_scalar_v<_Tp>)
|
||||
{
|
||||
const auto __tmp = __value;
|
||||
for (; __n > 0; --__n, (void)++__first)
|
||||
*__first = __tmp;
|
||||
return __first;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; __n > 0; --__n, (void)++__first)
|
||||
*__first = __value;
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Tp, output_range<const _Tp&> _Range>
|
||||
constexpr safe_iterator_t<_Range>
|
||||
fill(_Range&& __r, const _Tp& __value)
|
||||
{
|
||||
return ranges::fill(ranges::begin(__r), ranges::end(__r), __value);
|
||||
}
|
||||
inline constexpr __fill_n_fn fill_n{};
|
||||
|
||||
struct __fill_fn
|
||||
{
|
||||
template<typename _Tp,
|
||||
output_iterator<const _Tp&> _Out, sentinel_for<_Out> _Sent>
|
||||
constexpr _Out
|
||||
operator()(_Out __first, _Sent __last, const _Tp& __value) const
|
||||
{
|
||||
// TODO: implement more specializations to be at least on par with
|
||||
// std::fill
|
||||
if constexpr (sized_sentinel_for<_Sent, _Out>)
|
||||
{
|
||||
const auto __len = __last - __first;
|
||||
return ranges::fill_n(__first, __len, __value);
|
||||
}
|
||||
else if constexpr (is_scalar_v<_Tp>)
|
||||
{
|
||||
const auto __tmp = __value;
|
||||
for (; __first != __last; ++__first)
|
||||
*__first = __tmp;
|
||||
return __first;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; __first != __last; ++__first)
|
||||
*__first = __value;
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp, output_range<const _Tp&> _Range>
|
||||
constexpr safe_iterator_t<_Range>
|
||||
operator()(_Range&& __r, const _Tp& __value) const
|
||||
{
|
||||
return (*this)(ranges::begin(__r), ranges::end(__r), __value);
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __fill_fn fill{};
|
||||
}
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
@ -78,11 +78,21 @@ namespace ranges
|
||||
&& __nothrow_forward_iterator<iterator_t<_Range>>);
|
||||
} // namespace __detail
|
||||
|
||||
template<__detail::__nothrow_input_iterator _Iter,
|
||||
__detail::__nothrow_sentinel<_Iter> _Sent>
|
||||
requires destructible<iter_value_t<_Iter>>
|
||||
constexpr _Iter
|
||||
destroy(_Iter __first, _Sent __last) noexcept;
|
||||
struct __destroy_fn
|
||||
{
|
||||
template<__detail::__nothrow_input_iterator _Iter,
|
||||
__detail::__nothrow_sentinel<_Iter> _Sent>
|
||||
requires destructible<iter_value_t<_Iter>>
|
||||
constexpr _Iter
|
||||
operator()(_Iter __first, _Sent __last) const noexcept;
|
||||
|
||||
template<__detail::__nothrow_input_range _Range>
|
||||
requires destructible<range_value_t<_Range>>
|
||||
constexpr safe_iterator_t<_Range>
|
||||
operator()(_Range&& __r) const noexcept;
|
||||
};
|
||||
|
||||
inline constexpr __destroy_fn destroy{};
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
@ -126,332 +136,396 @@ namespace ranges
|
||||
};
|
||||
} // namespace __detail
|
||||
|
||||
template<__detail::__nothrow_forward_iterator _Iter,
|
||||
__detail::__nothrow_sentinel<_Iter> _Sent>
|
||||
requires default_initializable<iter_value_t<_Iter>>
|
||||
_Iter
|
||||
uninitialized_default_construct(_Iter __first, _Sent __last)
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivially_default_constructible_v<_ValueType>)
|
||||
return ranges::next(__first, __last);
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __first != __last; ++__first)
|
||||
::new (__detail::__voidify(*__first)) _ValueType;
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
struct __uninitialized_default_construct_fn
|
||||
{
|
||||
template<__detail::__nothrow_forward_iterator _Iter,
|
||||
__detail::__nothrow_sentinel<_Iter> _Sent>
|
||||
requires default_initializable<iter_value_t<_Iter>>
|
||||
_Iter
|
||||
operator()(_Iter __first, _Sent __last) const
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivially_default_constructible_v<_ValueType>)
|
||||
return ranges::next(__first, __last);
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __first != __last; ++__first)
|
||||
::new (__detail::__voidify(*__first)) _ValueType;
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
|
||||
template<__detail::__nothrow_forward_range _Range>
|
||||
requires default_initializable<range_value_t<_Range>>
|
||||
safe_iterator_t<_Range>
|
||||
uninitialized_default_construct(_Range&& __r)
|
||||
{
|
||||
return ranges::uninitialized_default_construct(ranges::begin(__r),
|
||||
template<__detail::__nothrow_forward_range _Range>
|
||||
requires default_initializable<range_value_t<_Range>>
|
||||
safe_iterator_t<_Range>
|
||||
operator()(_Range&& __r) const
|
||||
{
|
||||
return (*this)(ranges::begin(__r),
|
||||
ranges::end(__r));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __uninitialized_default_construct_fn
|
||||
uninitialized_default_construct{};
|
||||
|
||||
struct __uninitialized_default_construct_n_fn
|
||||
{
|
||||
template<__detail::__nothrow_forward_iterator _Iter>
|
||||
requires default_initializable<iter_value_t<_Iter>>
|
||||
_Iter
|
||||
operator()(_Iter __first,
|
||||
iter_difference_t<_Iter> __n) const
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivially_default_constructible_v<_ValueType>)
|
||||
return ranges::next(__first, __n);
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __n > 0; ++__first, (void) --__n)
|
||||
::new (__detail::__voidify(*__first)) _ValueType;
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __uninitialized_default_construct_n_fn
|
||||
uninitialized_default_construct_n;
|
||||
|
||||
struct __uninitialized_value_construct_fn
|
||||
{
|
||||
template<__detail::__nothrow_forward_iterator _Iter,
|
||||
__detail::__nothrow_sentinel<_Iter> _Sent>
|
||||
requires default_initializable<iter_value_t<_Iter>>
|
||||
_Iter
|
||||
operator()(_Iter __first, _Sent __last) const
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivial_v<_ValueType>
|
||||
&& is_copy_assignable_v<_ValueType>)
|
||||
return ranges::fill(__first, __last, _ValueType());
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __first != __last; ++__first)
|
||||
::new (__detail::__voidify(*__first)) _ValueType();
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
|
||||
template<__detail::__nothrow_forward_range _Range>
|
||||
requires default_initializable<range_value_t<_Range>>
|
||||
safe_iterator_t<_Range>
|
||||
operator()(_Range&& __r) const
|
||||
{
|
||||
return (*this)(ranges::begin(__r),
|
||||
ranges::end(__r));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<__detail::__nothrow_forward_iterator _Iter>
|
||||
requires default_initializable<iter_value_t<_Iter>>
|
||||
_Iter
|
||||
uninitialized_default_construct_n(_Iter __first,
|
||||
iter_difference_t<_Iter> __n)
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivially_default_constructible_v<_ValueType>)
|
||||
return ranges::next(__first, __n);
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __n > 0; ++__first, (void) --__n)
|
||||
::new (__detail::__voidify(*__first)) _ValueType;
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
inline constexpr __uninitialized_value_construct_fn
|
||||
uninitialized_value_construct{};
|
||||
|
||||
template<__detail::__nothrow_forward_iterator _Iter,
|
||||
__detail::__nothrow_sentinel<_Iter> _Sent>
|
||||
requires default_initializable<iter_value_t<_Iter>>
|
||||
_Iter
|
||||
uninitialized_value_construct(_Iter __first, _Sent __last)
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivial_v<_ValueType>
|
||||
&& is_copy_assignable_v<_ValueType>)
|
||||
return ranges::fill(__first, __last, _ValueType());
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __first != __last; ++__first)
|
||||
::new (__detail::__voidify(*__first)) _ValueType();
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
struct __uninitialized_value_construct_n_fn
|
||||
{
|
||||
template<__detail::__nothrow_forward_iterator _Iter>
|
||||
requires default_initializable<iter_value_t<_Iter>>
|
||||
_Iter
|
||||
operator()(_Iter __first, iter_difference_t<_Iter> __n) const
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivial_v<_ValueType>
|
||||
&& is_copy_assignable_v<_ValueType>)
|
||||
return ranges::fill_n(__first, __n, _ValueType());
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __n > 0; ++__first, (void) --__n)
|
||||
::new (__detail::__voidify(*__first)) _ValueType();
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<__detail::__nothrow_forward_range _Range>
|
||||
requires default_initializable<range_value_t<_Range>>
|
||||
safe_iterator_t<_Range>
|
||||
uninitialized_value_construct(_Range&& __r)
|
||||
{
|
||||
return ranges::uninitialized_value_construct(ranges::begin(__r),
|
||||
ranges::end(__r));
|
||||
}
|
||||
|
||||
template<__detail::__nothrow_forward_iterator _Iter>
|
||||
requires default_initializable<iter_value_t<_Iter>>
|
||||
_Iter
|
||||
uninitialized_value_construct_n(_Iter __first, iter_difference_t<_Iter> __n)
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivial_v<_ValueType>
|
||||
&& is_copy_assignable_v<_ValueType>)
|
||||
return ranges::fill_n(__first, __n, _ValueType());
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __n > 0; ++__first, (void) --__n)
|
||||
::new (__detail::__voidify(*__first)) _ValueType();
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
inline constexpr __uninitialized_value_construct_n_fn
|
||||
uninitialized_value_construct_n;
|
||||
|
||||
template<typename _Iter, typename _Out>
|
||||
using uninitialized_copy_result = copy_result<_Iter, _Out>;
|
||||
|
||||
template<input_iterator _Iter, sentinel_for<_Iter> _ISent,
|
||||
__detail::__nothrow_forward_iterator _Out,
|
||||
__detail::__nothrow_sentinel<_Out> _OSent>
|
||||
requires constructible_from<iter_value_t<_Out>, iter_reference_t<_Iter>>
|
||||
uninitialized_copy_result<_Iter, _Out>
|
||||
uninitialized_copy(_Iter __ifirst, _ISent __ilast,
|
||||
_Out __ofirst, _OSent __olast)
|
||||
{
|
||||
using _OutType = remove_reference_t<iter_reference_t<_Out>>;
|
||||
if constexpr (sized_sentinel_for<_ISent, _Iter>
|
||||
&& sized_sentinel_for<_OSent, _Out>
|
||||
&& is_trivial_v<_OutType>
|
||||
&& is_nothrow_assignable_v<_OutType,
|
||||
iter_reference_t<_Iter>>)
|
||||
{
|
||||
auto __d1 = ranges::distance(__ifirst, __ilast);
|
||||
auto __d2 = ranges::distance(__ofirst, __olast);
|
||||
return ranges::copy_n(__ifirst, std::min(__d1, __d2), __ofirst);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__ofirst);
|
||||
for (; __ifirst != __ilast && __ofirst != __olast;
|
||||
++__ofirst, (void)++__ifirst)
|
||||
::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst);
|
||||
__guard.release();
|
||||
return {__ifirst, __ofirst};
|
||||
}
|
||||
}
|
||||
struct __uninitialized_copy_fn
|
||||
{
|
||||
template<input_iterator _Iter, sentinel_for<_Iter> _ISent,
|
||||
__detail::__nothrow_forward_iterator _Out,
|
||||
__detail::__nothrow_sentinel<_Out> _OSent>
|
||||
requires constructible_from<iter_value_t<_Out>, iter_reference_t<_Iter>>
|
||||
uninitialized_copy_result<_Iter, _Out>
|
||||
operator()(_Iter __ifirst, _ISent __ilast,
|
||||
_Out __ofirst, _OSent __olast) const
|
||||
{
|
||||
using _OutType = remove_reference_t<iter_reference_t<_Out>>;
|
||||
if constexpr (sized_sentinel_for<_ISent, _Iter>
|
||||
&& sized_sentinel_for<_OSent, _Out>
|
||||
&& is_trivial_v<_OutType>
|
||||
&& is_nothrow_assignable_v<_OutType,
|
||||
iter_reference_t<_Iter>>)
|
||||
{
|
||||
auto __d1 = ranges::distance(__ifirst, __ilast);
|
||||
auto __d2 = ranges::distance(__ofirst, __olast);
|
||||
return ranges::copy_n(__ifirst, std::min(__d1, __d2), __ofirst);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__ofirst);
|
||||
for (; __ifirst != __ilast && __ofirst != __olast;
|
||||
++__ofirst, (void)++__ifirst)
|
||||
::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst);
|
||||
__guard.release();
|
||||
return {__ifirst, __ofirst};
|
||||
}
|
||||
}
|
||||
|
||||
template<input_range _IRange, __detail::__nothrow_forward_range _ORange>
|
||||
requires constructible_from<range_value_t<_ORange>,
|
||||
range_reference_t<_IRange>>
|
||||
uninitialized_copy_result<safe_iterator_t<_IRange>,
|
||||
safe_iterator_t<_ORange>>
|
||||
uninitialized_copy(_IRange&& __inr, _ORange&& __outr)
|
||||
{
|
||||
return ranges::uninitialized_copy(ranges::begin(__inr),
|
||||
ranges::end(__inr),
|
||||
ranges::begin(__outr),
|
||||
ranges::end(__outr));
|
||||
}
|
||||
template<input_range _IRange, __detail::__nothrow_forward_range _ORange>
|
||||
requires constructible_from<range_value_t<_ORange>,
|
||||
range_reference_t<_IRange>>
|
||||
uninitialized_copy_result<safe_iterator_t<_IRange>,
|
||||
safe_iterator_t<_ORange>>
|
||||
operator()(_IRange&& __inr, _ORange&& __outr) const
|
||||
{
|
||||
return (*this)(ranges::begin(__inr),
|
||||
ranges::end(__inr),
|
||||
ranges::begin(__outr),
|
||||
ranges::end(__outr));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __uninitialized_copy_fn uninitialized_copy{};
|
||||
|
||||
template<typename _Iter, typename _Out>
|
||||
using uninitialized_copy_n_result = uninitialized_copy_result<_Iter, _Out>;
|
||||
|
||||
struct __uninitialized_copy_n_fn
|
||||
{
|
||||
template<input_iterator _Iter, __detail::__nothrow_forward_iterator _Out,
|
||||
__detail::__nothrow_sentinel<_Out> _Sent>
|
||||
requires constructible_from<iter_value_t<_Out>, iter_reference_t<_Iter>>
|
||||
uninitialized_copy_n_result<_Iter, _Out>
|
||||
uninitialized_copy_n(_Iter __ifirst, iter_difference_t<_Iter> __n,
|
||||
_Out __ofirst, _Sent __olast)
|
||||
{
|
||||
using _OutType = remove_reference_t<iter_reference_t<_Out>>;
|
||||
if constexpr (sized_sentinel_for<_Sent, _Out>
|
||||
&& is_trivial_v<_OutType>
|
||||
&& is_nothrow_assignable_v<_OutType,
|
||||
iter_reference_t<_Iter>>)
|
||||
{
|
||||
auto __d = ranges::distance(__ofirst, __olast);
|
||||
return ranges::copy_n(__ifirst, std::min(__n, __d), __ofirst);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__ofirst);
|
||||
for (; __n > 0 && __ofirst != __olast;
|
||||
++__ofirst, (void)++__ifirst, (void)--__n)
|
||||
::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst);
|
||||
__guard.release();
|
||||
return {__ifirst, __ofirst};
|
||||
}
|
||||
}
|
||||
__detail::__nothrow_sentinel<_Out> _Sent>
|
||||
requires constructible_from<iter_value_t<_Out>, iter_reference_t<_Iter>>
|
||||
uninitialized_copy_n_result<_Iter, _Out>
|
||||
operator()(_Iter __ifirst, iter_difference_t<_Iter> __n,
|
||||
_Out __ofirst, _Sent __olast) const
|
||||
{
|
||||
using _OutType = remove_reference_t<iter_reference_t<_Out>>;
|
||||
if constexpr (sized_sentinel_for<_Sent, _Out>
|
||||
&& is_trivial_v<_OutType>
|
||||
&& is_nothrow_assignable_v<_OutType,
|
||||
iter_reference_t<_Iter>>)
|
||||
{
|
||||
auto __d = ranges::distance(__ofirst, __olast);
|
||||
return ranges::copy_n(__ifirst, std::min(__n, __d), __ofirst);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__ofirst);
|
||||
for (; __n > 0 && __ofirst != __olast;
|
||||
++__ofirst, (void)++__ifirst, (void)--__n)
|
||||
::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst);
|
||||
__guard.release();
|
||||
return {__ifirst, __ofirst};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __uninitialized_copy_n_fn uninitialized_copy_n{};
|
||||
|
||||
template<typename _Iter, typename _Out>
|
||||
using uninitialized_move_result = uninitialized_copy_result<_Iter, _Out>;
|
||||
|
||||
template<input_iterator _Iter, sentinel_for<_Iter> _ISent,
|
||||
__detail::__nothrow_forward_iterator _Out,
|
||||
__detail::__nothrow_sentinel<_Out> _OSent>
|
||||
requires constructible_from<iter_value_t<_Out>,
|
||||
iter_rvalue_reference_t<_Iter>>
|
||||
uninitialized_move_result<_Iter, _Out>
|
||||
uninitialized_move(_Iter __ifirst, _ISent __ilast,
|
||||
_Out __ofirst, _OSent __olast)
|
||||
{
|
||||
using _OutType = remove_reference_t<iter_reference_t<_Out>>;
|
||||
if constexpr (sized_sentinel_for<_ISent, _Iter>
|
||||
&& sized_sentinel_for<_OSent, _Out>
|
||||
&& is_trivial_v<_OutType>
|
||||
&& is_nothrow_assignable_v<_OutType,
|
||||
iter_rvalue_reference_t<_Iter>>)
|
||||
{
|
||||
auto __d1 = ranges::distance(__ifirst, __ilast);
|
||||
auto __d2 = ranges::distance(__ofirst, __olast);
|
||||
return ranges::copy_n(std::make_move_iterator(__ifirst),
|
||||
std::min(__d1, __d2), __ofirst);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__ofirst);
|
||||
for (; __ifirst != __ilast && __ofirst != __olast;
|
||||
++__ofirst, (void)++__ifirst)
|
||||
::new (__detail::__voidify(*__ofirst))
|
||||
_OutType(ranges::iter_move(__ifirst));
|
||||
__guard.release();
|
||||
return {__ifirst, __ofirst};
|
||||
}
|
||||
}
|
||||
struct __uninitialized_move_fn
|
||||
{
|
||||
template<input_iterator _Iter, sentinel_for<_Iter> _ISent,
|
||||
__detail::__nothrow_forward_iterator _Out,
|
||||
__detail::__nothrow_sentinel<_Out> _OSent>
|
||||
requires constructible_from<iter_value_t<_Out>,
|
||||
iter_rvalue_reference_t<_Iter>>
|
||||
uninitialized_move_result<_Iter, _Out>
|
||||
operator()(_Iter __ifirst, _ISent __ilast,
|
||||
_Out __ofirst, _OSent __olast) const
|
||||
{
|
||||
using _OutType = remove_reference_t<iter_reference_t<_Out>>;
|
||||
if constexpr (sized_sentinel_for<_ISent, _Iter>
|
||||
&& sized_sentinel_for<_OSent, _Out>
|
||||
&& is_trivial_v<_OutType>
|
||||
&& is_nothrow_assignable_v<_OutType,
|
||||
iter_rvalue_reference_t<_Iter>>)
|
||||
{
|
||||
auto __d1 = ranges::distance(__ifirst, __ilast);
|
||||
auto __d2 = ranges::distance(__ofirst, __olast);
|
||||
return ranges::copy_n(std::make_move_iterator(__ifirst),
|
||||
std::min(__d1, __d2), __ofirst);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__ofirst);
|
||||
for (; __ifirst != __ilast && __ofirst != __olast;
|
||||
++__ofirst, (void)++__ifirst)
|
||||
::new (__detail::__voidify(*__ofirst))
|
||||
_OutType(ranges::iter_move(__ifirst));
|
||||
__guard.release();
|
||||
return {__ifirst, __ofirst};
|
||||
}
|
||||
}
|
||||
|
||||
template<input_range _IRange, __detail::__nothrow_forward_range _ORange>
|
||||
requires constructible_from<range_value_t<_ORange>,
|
||||
range_rvalue_reference_t<_IRange>>
|
||||
uninitialized_move_result<safe_iterator_t<_IRange>,
|
||||
safe_iterator_t<_ORange>>
|
||||
uninitialized_move(_IRange&& __inr, _ORange&& __outr)
|
||||
{
|
||||
return ranges::uninitialized_move(ranges::begin(__inr),
|
||||
ranges::end(__inr),
|
||||
ranges::begin(__outr),
|
||||
ranges::end(__outr));
|
||||
}
|
||||
template<input_range _IRange, __detail::__nothrow_forward_range _ORange>
|
||||
requires constructible_from<range_value_t<_ORange>,
|
||||
range_rvalue_reference_t<_IRange>>
|
||||
uninitialized_move_result<safe_iterator_t<_IRange>,
|
||||
safe_iterator_t<_ORange>>
|
||||
operator()(_IRange&& __inr, _ORange&& __outr) const
|
||||
{
|
||||
return (*this)(ranges::begin(__inr),
|
||||
ranges::end(__inr),
|
||||
ranges::begin(__outr),
|
||||
ranges::end(__outr));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __uninitialized_move_fn uninitialized_move{};
|
||||
|
||||
template<typename _Iter, typename _Out>
|
||||
using uninitialized_move_n_result = uninitialized_copy_result<_Iter, _Out>;
|
||||
|
||||
template<input_iterator _Iter, __detail::__nothrow_forward_iterator _Out,
|
||||
__detail::__nothrow_sentinel<_Out> _Sent>
|
||||
requires constructible_from<iter_value_t<_Out>,
|
||||
iter_rvalue_reference_t<_Iter>>
|
||||
uninitialized_move_n_result<_Iter, _Out>
|
||||
uninitialized_move_n(_Iter __ifirst, iter_difference_t<_Iter> __n,
|
||||
_Out __ofirst, _Sent __olast)
|
||||
{
|
||||
using _OutType = remove_reference_t<iter_reference_t<_Out>>;
|
||||
if constexpr (sized_sentinel_for<_Sent, _Out>
|
||||
&& is_trivial_v<_OutType>
|
||||
&& is_nothrow_assignable_v<_OutType,
|
||||
iter_rvalue_reference_t<_Iter>>)
|
||||
{
|
||||
auto __d = ranges::distance(__ofirst, __olast);
|
||||
return ranges::copy_n(std::make_move_iterator(__ifirst),
|
||||
std::min(__n, __d), __ofirst);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__ofirst);
|
||||
for (; __n > 0 && __ofirst != __olast;
|
||||
++__ofirst, (void)++__ifirst, (void)--__n)
|
||||
::new (__detail::__voidify(*__ofirst))
|
||||
_OutType(ranges::iter_move(__ifirst));
|
||||
__guard.release();
|
||||
return {__ifirst, __ofirst};
|
||||
}
|
||||
}
|
||||
struct __uninitialized_move_n_fn
|
||||
{
|
||||
template<input_iterator _Iter, __detail::__nothrow_forward_iterator _Out,
|
||||
__detail::__nothrow_sentinel<_Out> _Sent>
|
||||
requires constructible_from<iter_value_t<_Out>,
|
||||
iter_rvalue_reference_t<_Iter>>
|
||||
uninitialized_move_n_result<_Iter, _Out>
|
||||
operator()(_Iter __ifirst, iter_difference_t<_Iter> __n,
|
||||
_Out __ofirst, _Sent __olast) const
|
||||
{
|
||||
using _OutType = remove_reference_t<iter_reference_t<_Out>>;
|
||||
if constexpr (sized_sentinel_for<_Sent, _Out>
|
||||
&& is_trivial_v<_OutType>
|
||||
&& is_nothrow_assignable_v<_OutType,
|
||||
iter_rvalue_reference_t<_Iter>>)
|
||||
{
|
||||
auto __d = ranges::distance(__ofirst, __olast);
|
||||
return ranges::copy_n(std::make_move_iterator(__ifirst),
|
||||
std::min(__n, __d), __ofirst);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__ofirst);
|
||||
for (; __n > 0 && __ofirst != __olast;
|
||||
++__ofirst, (void)++__ifirst, (void)--__n)
|
||||
::new (__detail::__voidify(*__ofirst))
|
||||
_OutType(ranges::iter_move(__ifirst));
|
||||
__guard.release();
|
||||
return {__ifirst, __ofirst};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<__detail::__nothrow_forward_iterator _Iter,
|
||||
__detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp>
|
||||
requires constructible_from<iter_value_t<_Iter>, const _Tp&>
|
||||
_Iter
|
||||
uninitialized_fill(_Iter __first, _Sent __last, const _Tp& __x)
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivial_v<_ValueType>
|
||||
&& is_nothrow_assignable_v<_ValueType, const _Tp&>)
|
||||
return ranges::fill(__first, __last, __x);
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __first != __last; ++__first)
|
||||
::new (__detail::__voidify(*__first)) _ValueType(__x);
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
inline constexpr __uninitialized_move_n_fn uninitialized_move_n{};
|
||||
|
||||
template<__detail::__nothrow_forward_range _Range, typename _Tp>
|
||||
requires constructible_from<range_value_t<_Range>, const _Tp&>
|
||||
safe_iterator_t<_Range>
|
||||
uninitialized_fill(_Range&& __r, const _Tp& __x)
|
||||
{
|
||||
return ranges::uninitialized_fill(ranges::begin(__r), ranges::end(__r),
|
||||
__x);
|
||||
}
|
||||
struct __uninitialized_fill_fn
|
||||
{
|
||||
template<__detail::__nothrow_forward_iterator _Iter,
|
||||
__detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp>
|
||||
requires constructible_from<iter_value_t<_Iter>, const _Tp&>
|
||||
_Iter
|
||||
operator()(_Iter __first, _Sent __last, const _Tp& __x) const
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivial_v<_ValueType>
|
||||
&& is_nothrow_assignable_v<_ValueType, const _Tp&>)
|
||||
return ranges::fill(__first, __last, __x);
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __first != __last; ++__first)
|
||||
::new (__detail::__voidify(*__first)) _ValueType(__x);
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
|
||||
template<__detail::__nothrow_forward_iterator _Iter, typename _Tp>
|
||||
requires constructible_from<iter_value_t<_Iter>, const _Tp&>
|
||||
_Iter
|
||||
uninitialized_fill_n(_Iter __first, iter_difference_t<_Iter> __n,
|
||||
const _Tp& __x)
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivial_v<_ValueType>
|
||||
&& is_nothrow_assignable_v<_ValueType, const _Tp&>)
|
||||
return ranges::fill_n(__first, __n, __x);
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __n > 0; ++__first, (void)--__n)
|
||||
::new (__detail::__voidify(*__first)) _ValueType(__x);
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
template<__detail::__nothrow_forward_range _Range, typename _Tp>
|
||||
requires constructible_from<range_value_t<_Range>, const _Tp&>
|
||||
safe_iterator_t<_Range>
|
||||
operator()(_Range&& __r, const _Tp& __x) const
|
||||
{
|
||||
return (*this)(ranges::begin(__r), ranges::end(__r),
|
||||
__x);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
requires requires { ::new (declval<void*>()) _Tp(declval<_Args>()...); }
|
||||
constexpr _Tp*
|
||||
construct_at(_Tp* __location, _Args&&... __args)
|
||||
{
|
||||
return ::new (__detail::__voidify(*__location))
|
||||
_Tp(std::forward<_Args>(__args)...);
|
||||
}
|
||||
inline constexpr __uninitialized_fill_fn uninitialized_fill{};
|
||||
|
||||
template<destructible _Tp>
|
||||
constexpr void
|
||||
destroy_at(_Tp* __location) noexcept
|
||||
{
|
||||
if constexpr (is_array_v<_Tp>)
|
||||
ranges::destroy(ranges::begin(*__location), ranges::end(*__location));
|
||||
else
|
||||
__location->~_Tp();
|
||||
}
|
||||
struct __uninitialized_fill_n_fn
|
||||
{
|
||||
template<__detail::__nothrow_forward_iterator _Iter, typename _Tp>
|
||||
requires constructible_from<iter_value_t<_Iter>, const _Tp&>
|
||||
_Iter
|
||||
operator()(_Iter __first, iter_difference_t<_Iter> __n,
|
||||
const _Tp& __x) const
|
||||
{
|
||||
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
|
||||
if constexpr (is_trivial_v<_ValueType>
|
||||
&& is_nothrow_assignable_v<_ValueType, const _Tp&>)
|
||||
return ranges::fill_n(__first, __n, __x);
|
||||
else
|
||||
{
|
||||
auto __guard = __detail::_DestroyGuard(&__first);
|
||||
for (; __n > 0; ++__first, (void)--__n)
|
||||
::new (__detail::__voidify(*__first)) _ValueType(__x);
|
||||
__guard.release();
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __uninitialized_fill_n_fn uninitialized_fill_n{};
|
||||
|
||||
struct __construct_at_fn
|
||||
{
|
||||
template<typename _Tp, typename... _Args>
|
||||
requires requires { ::new (declval<void*>()) _Tp(declval<_Args>()...); }
|
||||
constexpr _Tp*
|
||||
operator()(_Tp* __location, _Args&&... __args) const
|
||||
{
|
||||
return ::new (__detail::__voidify(*__location))
|
||||
_Tp(std::forward<_Args>(__args)...);
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __construct_at_fn construct_at{};
|
||||
|
||||
struct __destroy_at_fn
|
||||
{
|
||||
template<destructible _Tp>
|
||||
constexpr void
|
||||
operator()(_Tp* __location) const noexcept
|
||||
{
|
||||
if constexpr (is_array_v<_Tp>)
|
||||
ranges::destroy(ranges::begin(*__location), ranges::end(*__location));
|
||||
else
|
||||
__location->~_Tp();
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __destroy_at_fn destroy_at{};
|
||||
|
||||
template<__detail::__nothrow_input_iterator _Iter,
|
||||
__detail::__nothrow_sentinel<_Iter> _Sent>
|
||||
requires destructible<iter_value_t<_Iter>>
|
||||
constexpr _Iter
|
||||
destroy(_Iter __first, _Sent __last) noexcept
|
||||
__destroy_fn::operator()(_Iter __first, _Sent __last) const noexcept
|
||||
{
|
||||
if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>)
|
||||
return ranges::next(__first, __last);
|
||||
@ -466,23 +540,28 @@ namespace ranges
|
||||
template<__detail::__nothrow_input_range _Range>
|
||||
requires destructible<range_value_t<_Range>>
|
||||
constexpr safe_iterator_t<_Range>
|
||||
destroy(_Range&& __r) noexcept
|
||||
{ return ranges::destroy(ranges::begin(__r), ranges::end(__r)); }
|
||||
__destroy_fn::operator()(_Range&& __r) const noexcept
|
||||
{ return (*this)(ranges::begin(__r), ranges::end(__r)); }
|
||||
|
||||
template<__detail::__nothrow_input_iterator _Iter>
|
||||
requires destructible<iter_value_t<_Iter>>
|
||||
constexpr _Iter
|
||||
destroy_n(_Iter __first, iter_difference_t<_Iter> __n) noexcept
|
||||
{
|
||||
if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>)
|
||||
return ranges::next(__first, __n);
|
||||
else
|
||||
{
|
||||
for (; __n > 0; ++__first, (void)--__n)
|
||||
ranges::destroy_at(std::__addressof(*__first));
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
struct __destroy_n_fn
|
||||
{
|
||||
template<__detail::__nothrow_input_iterator _Iter>
|
||||
requires destructible<iter_value_t<_Iter>>
|
||||
constexpr _Iter
|
||||
operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept
|
||||
{
|
||||
if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>)
|
||||
return ranges::next(__first, __n);
|
||||
else
|
||||
{
|
||||
for (; __n > 0; ++__first, (void)--__n)
|
||||
ranges::destroy_at(std::__addressof(*__first));
|
||||
return __first;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr __destroy_n_fn destroy_n{};
|
||||
}
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
|
Loading…
x
Reference in New Issue
Block a user