Commit b40c57bd by Patrick Palka

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.
parent 90b7eb65
2020-02-15 Patrick Palka <ppalka@redhat.com> 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 ... * include/bits/ranges_algo.h (ranges::__find_end): Fold into ...
(ranges::find_end): ... here. (ranges::find_end): ... here.
(ranges::__lexicographical_compare): Fold into ... (ranges::__lexicographical_compare): Fold into ...
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -71,88 +71,93 @@ namespace ranges ...@@ -71,88 +71,93 @@ namespace ranges
__is_move_iterator<move_iterator<_Iterator>> = true; __is_move_iterator<move_iterator<_Iterator>> = true;
} // namespace __detail } // namespace __detail
template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1, struct __equal_fn
input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, {
typename _Pred = ranges::equal_to, template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
typename _Proj1 = identity, typename _Proj2 = identity> input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> typename _Pred = ranges::equal_to,
constexpr bool typename _Proj1 = identity, typename _Proj2 = identity>
equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
_Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) constexpr bool
{ operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
// TODO: implement more specializations to at least have parity with _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const
// std::equal. {
if constexpr (__detail::__is_normal_iterator<_Iter1> // TODO: implement more specializations to at least have parity with
|| __detail::__is_normal_iterator<_Iter2>) // std::equal.
return ranges::equal(std::__niter_base(std::move(__first1)), if constexpr (__detail::__is_normal_iterator<_Iter1>
std::__niter_base(std::move(__last1)), || __detail::__is_normal_iterator<_Iter2>)
std::__niter_base(std::move(__first2)), return (*this)(std::__niter_base(std::move(__first1)),
std::__niter_base(std::move(__last2)), 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(__pred),
std::move(__proj1), std::move(__proj2)); std::move(__proj1), std::move(__proj2));
}
};
constexpr bool __sized_iters inline constexpr __equal_fn equal{};
= (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));
}
template<typename _Iter, typename _Out> template<typename _Iter, typename _Out>
struct copy_result struct copy_result
...@@ -288,45 +293,55 @@ namespace ranges ...@@ -288,45 +293,55 @@ namespace ranges
} }
} }
template<input_iterator _Iter, sentinel_for<_Iter> _Sent, struct __copy_fn
weakly_incrementable _Out> {
requires indirectly_copyable<_Iter, _Out> template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
constexpr copy_result<_Iter, _Out> weakly_incrementable _Out>
copy(_Iter __first, _Sent __last, _Out __result) requires indirectly_copyable<_Iter, _Out>
{ constexpr copy_result<_Iter, _Out>
return ranges::__copy_or_move<false>(std::move(__first), operator()(_Iter __first, _Sent __last, _Out __result) const
std::move(__last), {
std::move(__result)); 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> template<input_range _Range, weakly_incrementable _Out>
copy(_Range&& __r, _Out __result) requires indirectly_copyable<iterator_t<_Range>, _Out>
{ constexpr copy_result<safe_iterator_t<_Range>, _Out>
return ranges::copy(ranges::begin(__r), ranges::end(__r), operator()(_Range&& __r, _Out __result) const
std::move(__result)); {
} 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> inline constexpr __copy_fn copy{};
move(_Iter __first, _Sent __last, _Out __result)
{ struct __move_fn
return ranges::__copy_or_move<true>(std::move(__first), {
std::move(__last), template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
std::move(__result)); weakly_incrementable _Out>
} requires indirectly_movable<_Iter, _Out>
constexpr move_result<_Iter, _Out>
template<input_range _Range, weakly_incrementable _Out> operator()(_Iter __first, _Sent __last, _Out __result) const
requires indirectly_movable<iterator_t<_Range>, _Out> {
constexpr move_result<safe_iterator_t<_Range>, _Out> return ranges::__copy_or_move<true>(std::move(__first),
move(_Range&& __r, _Out __result) std::move(__last),
{ std::move(__result));
return ranges::move(ranges::begin(__r), ranges::end(__r), }
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, template<bool _IsMove,
bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
...@@ -420,127 +435,152 @@ namespace ranges ...@@ -420,127 +435,152 @@ namespace ranges
} }
} }
template<bidirectional_iterator _Iter1, sentinel_for<_Iter1> _Sent1, struct __copy_backward_fn
bidirectional_iterator _Iter2> {
requires indirectly_copyable<_Iter1, _Iter2> template<bidirectional_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
constexpr copy_backward_result<_Iter1, _Iter2> bidirectional_iterator _Iter2>
copy_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result) requires indirectly_copyable<_Iter1, _Iter2>
{ constexpr copy_backward_result<_Iter1, _Iter2>
return ranges::__copy_or_move_backward<false>(std::move(__first), operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const
std::move(__last), {
std::move(__result)); 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> template<bidirectional_range _Range, bidirectional_iterator _Iter>
copy_backward(_Range&& __r, _Iter __result) requires indirectly_copyable<iterator_t<_Range>, _Iter>
{ constexpr copy_backward_result<safe_iterator_t<_Range>, _Iter>
return ranges::copy_backward(ranges::begin(__r), ranges::end(__r), operator()(_Range&& __r, _Iter __result) const
std::move(__result)); {
} 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> inline constexpr __copy_backward_fn copy_backward{};
move_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result)
{ struct __move_backward_fn
return ranges::__copy_or_move_backward<true>(std::move(__first), {
std::move(__last), template<bidirectional_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
std::move(__result)); bidirectional_iterator _Iter2>
} requires indirectly_movable<_Iter1, _Iter2>
constexpr move_backward_result<_Iter1, _Iter2>
template<bidirectional_range _Range, bidirectional_iterator _Iter> operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const
requires indirectly_movable<iterator_t<_Range>, _Iter> {
constexpr move_backward_result<safe_iterator_t<_Range>, _Iter> return ranges::__copy_or_move_backward<true>(std::move(__first),
move_backward(_Range&& __r, _Iter __result) std::move(__last),
{ std::move(__result));
return ranges::move_backward(ranges::begin(__r), ranges::end(__r), }
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> template<typename _Iter, typename _Out>
using copy_n_result = copy_result<_Iter, _Out>; using copy_n_result = copy_result<_Iter, _Out>;
template<input_iterator _Iter, weakly_incrementable _Out> struct __copy_n_fn
requires indirectly_copyable<_Iter, _Out> {
constexpr copy_n_result<_Iter, _Out> template<input_iterator _Iter, weakly_incrementable _Out>
copy_n(_Iter __first, iter_difference_t<_Iter> __n, _Out __result) requires indirectly_copyable<_Iter, _Out>
{ constexpr copy_n_result<_Iter, _Out>
if constexpr (random_access_iterator<_Iter>) operator()(_Iter __first, iter_difference_t<_Iter> __n, _Out __result) const
return ranges::copy(__first, __first + __n, std::move(__result)); {
else if constexpr (random_access_iterator<_Iter>)
{ return ranges::copy(__first, __first + __n, std::move(__result));
for (; __n > 0; --__n, (void)++__result, (void)++__first) else
*__result = *__first; {
return {std::move(__first), std::move(__result)}; 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)
{ inline constexpr __copy_n_fn copy_n{};
// TODO: implement more specializations to be at least on par with
// std::fill_n struct __fill_n_fn
if (__n <= 0) {
return __first; template<typename _Tp, output_iterator<const _Tp&> _Out>
constexpr _Out
// TODO: is __is_byte the best condition? operator()(_Out __first, iter_difference_t<_Out> __n, const _Tp& __value) const
if constexpr (is_pointer_v<_Out> && __is_byte<_Tp>::__value) {
{ // TODO: implement more specializations to be at least on par with
__builtin_memset(__first, static_cast<unsigned char>(__value), __n); // std::fill_n
return __first + __n; if (__n <= 0)
}
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_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; return __first;
}
}
template<typename _Tp, output_range<const _Tp&> _Range> // TODO: is __is_byte the best condition?
constexpr safe_iterator_t<_Range> if constexpr (is_pointer_v<_Out> && __is_byte<_Tp>::__value)
fill(_Range&& __r, const _Tp& __value) {
{ __builtin_memset(__first, static_cast<unsigned char>(__value), __n);
return ranges::fill(ranges::begin(__r), ranges::end(__r), __value); 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;
}
}
};
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 _GLIBCXX_END_NAMESPACE_VERSION
} // namespace std } // namespace std
......
...@@ -78,11 +78,21 @@ namespace ranges ...@@ -78,11 +78,21 @@ namespace ranges
&& __nothrow_forward_iterator<iterator_t<_Range>>); && __nothrow_forward_iterator<iterator_t<_Range>>);
} // namespace __detail } // namespace __detail
template<__detail::__nothrow_input_iterator _Iter, struct __destroy_fn
__detail::__nothrow_sentinel<_Iter> _Sent> {
requires destructible<iter_value_t<_Iter>> template<__detail::__nothrow_input_iterator _Iter,
constexpr _Iter __detail::__nothrow_sentinel<_Iter> _Sent>
destroy(_Iter __first, _Sent __last) noexcept; 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 namespace __detail
{ {
...@@ -126,332 +136,396 @@ namespace ranges ...@@ -126,332 +136,396 @@ namespace ranges
}; };
} // namespace __detail } // namespace __detail
template<__detail::__nothrow_forward_iterator _Iter, struct __uninitialized_default_construct_fn
__detail::__nothrow_sentinel<_Iter> _Sent> {
requires default_initializable<iter_value_t<_Iter>> template<__detail::__nothrow_forward_iterator _Iter,
_Iter __detail::__nothrow_sentinel<_Iter> _Sent>
uninitialized_default_construct(_Iter __first, _Sent __last) requires default_initializable<iter_value_t<_Iter>>
{ _Iter
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; operator()(_Iter __first, _Sent __last) const
if constexpr (is_trivially_default_constructible_v<_ValueType>) {
return ranges::next(__first, __last); using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
else if constexpr (is_trivially_default_constructible_v<_ValueType>)
{ return ranges::next(__first, __last);
auto __guard = __detail::_DestroyGuard(&__first); else
for (; __first != __last; ++__first) {
::new (__detail::__voidify(*__first)) _ValueType; auto __guard = __detail::_DestroyGuard(&__first);
__guard.release(); for (; __first != __last; ++__first)
return __first; ::new (__detail::__voidify(*__first)) _ValueType;
} __guard.release();
} return __first;
}
}
template<__detail::__nothrow_forward_range _Range> template<__detail::__nothrow_forward_range _Range>
requires default_initializable<range_value_t<_Range>> requires default_initializable<range_value_t<_Range>>
safe_iterator_t<_Range> safe_iterator_t<_Range>
uninitialized_default_construct(_Range&& __r) operator()(_Range&& __r) const
{ {
return ranges::uninitialized_default_construct(ranges::begin(__r), return (*this)(ranges::begin(__r),
ranges::end(__r)); ranges::end(__r));
} }
};
template<__detail::__nothrow_forward_iterator _Iter> inline constexpr __uninitialized_default_construct_fn
requires default_initializable<iter_value_t<_Iter>> uninitialized_default_construct{};
_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;
}
}
template<__detail::__nothrow_forward_iterator _Iter, struct __uninitialized_default_construct_n_fn
__detail::__nothrow_sentinel<_Iter> _Sent> {
requires default_initializable<iter_value_t<_Iter>> template<__detail::__nothrow_forward_iterator _Iter>
_Iter requires default_initializable<iter_value_t<_Iter>>
uninitialized_value_construct(_Iter __first, _Sent __last) _Iter
{ operator()(_Iter __first,
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; iter_difference_t<_Iter> __n) const
if constexpr (is_trivial_v<_ValueType> {
&& is_copy_assignable_v<_ValueType>) using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
return ranges::fill(__first, __last, _ValueType()); if constexpr (is_trivially_default_constructible_v<_ValueType>)
else return ranges::next(__first, __n);
{ else
auto __guard = __detail::_DestroyGuard(&__first); {
for (; __first != __last; ++__first) auto __guard = __detail::_DestroyGuard(&__first);
::new (__detail::__voidify(*__first)) _ValueType(); for (; __n > 0; ++__first, (void) --__n)
__guard.release(); ::new (__detail::__voidify(*__first)) _ValueType;
return __first; __guard.release();
} return __first;
} }
}
};
template<__detail::__nothrow_forward_range _Range> inline constexpr __uninitialized_default_construct_n_fn
requires default_initializable<range_value_t<_Range>> uninitialized_default_construct_n;
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> struct __uninitialized_value_construct_fn
requires default_initializable<iter_value_t<_Iter>> {
_Iter template<__detail::__nothrow_forward_iterator _Iter,
uninitialized_value_construct_n(_Iter __first, iter_difference_t<_Iter> __n) __detail::__nothrow_sentinel<_Iter> _Sent>
{ requires default_initializable<iter_value_t<_Iter>>
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; _Iter
if constexpr (is_trivial_v<_ValueType> operator()(_Iter __first, _Sent __last) const
&& is_copy_assignable_v<_ValueType>) {
return ranges::fill_n(__first, __n, _ValueType()); using _ValueType = remove_reference_t<iter_reference_t<_Iter>>;
else if constexpr (is_trivial_v<_ValueType>
{ && is_copy_assignable_v<_ValueType>)
auto __guard = __detail::_DestroyGuard(&__first); return ranges::fill(__first, __last, _ValueType());
for (; __n > 0; ++__first, (void) --__n) else
::new (__detail::__voidify(*__first)) _ValueType(); {
__guard.release(); auto __guard = __detail::_DestroyGuard(&__first);
return __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));
}
};
inline constexpr __uninitialized_value_construct_fn
uninitialized_value_construct{};
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;
}
}
};
inline constexpr __uninitialized_value_construct_n_fn
uninitialized_value_construct_n;
template<typename _Iter, typename _Out> template<typename _Iter, typename _Out>
using uninitialized_copy_result = copy_result<_Iter, _Out>; using uninitialized_copy_result = copy_result<_Iter, _Out>;
template<input_iterator _Iter, sentinel_for<_Iter> _ISent, struct __uninitialized_copy_fn
__detail::__nothrow_forward_iterator _Out, {
__detail::__nothrow_sentinel<_Out> _OSent> template<input_iterator _Iter, sentinel_for<_Iter> _ISent,
requires constructible_from<iter_value_t<_Out>, iter_reference_t<_Iter>> __detail::__nothrow_forward_iterator _Out,
uninitialized_copy_result<_Iter, _Out> __detail::__nothrow_sentinel<_Out> _OSent>
uninitialized_copy(_Iter __ifirst, _ISent __ilast, requires constructible_from<iter_value_t<_Out>, iter_reference_t<_Iter>>
_Out __ofirst, _OSent __olast) uninitialized_copy_result<_Iter, _Out>
{ operator()(_Iter __ifirst, _ISent __ilast,
using _OutType = remove_reference_t<iter_reference_t<_Out>>; _Out __ofirst, _OSent __olast) const
if constexpr (sized_sentinel_for<_ISent, _Iter> {
&& sized_sentinel_for<_OSent, _Out> using _OutType = remove_reference_t<iter_reference_t<_Out>>;
&& is_trivial_v<_OutType> if constexpr (sized_sentinel_for<_ISent, _Iter>
&& is_nothrow_assignable_v<_OutType, && sized_sentinel_for<_OSent, _Out>
iter_reference_t<_Iter>>) && is_trivial_v<_OutType>
{ && is_nothrow_assignable_v<_OutType,
auto __d1 = ranges::distance(__ifirst, __ilast); iter_reference_t<_Iter>>)
auto __d2 = ranges::distance(__ofirst, __olast); {
return ranges::copy_n(__ifirst, std::min(__d1, __d2), __ofirst); auto __d1 = ranges::distance(__ifirst, __ilast);
} auto __d2 = ranges::distance(__ofirst, __olast);
else return ranges::copy_n(__ifirst, std::min(__d1, __d2), __ofirst);
{ }
auto __guard = __detail::_DestroyGuard(&__ofirst); else
for (; __ifirst != __ilast && __ofirst != __olast; {
++__ofirst, (void)++__ifirst) auto __guard = __detail::_DestroyGuard(&__ofirst);
::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); for (; __ifirst != __ilast && __ofirst != __olast;
__guard.release(); ++__ofirst, (void)++__ifirst)
return {__ifirst, __ofirst}; ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst);
} __guard.release();
} return {__ifirst, __ofirst};
}
}
template<input_range _IRange, __detail::__nothrow_forward_range _ORange> template<input_range _IRange, __detail::__nothrow_forward_range _ORange>
requires constructible_from<range_value_t<_ORange>, requires constructible_from<range_value_t<_ORange>,
range_reference_t<_IRange>> range_reference_t<_IRange>>
uninitialized_copy_result<safe_iterator_t<_IRange>, uninitialized_copy_result<safe_iterator_t<_IRange>,
safe_iterator_t<_ORange>> safe_iterator_t<_ORange>>
uninitialized_copy(_IRange&& __inr, _ORange&& __outr) operator()(_IRange&& __inr, _ORange&& __outr) const
{ {
return ranges::uninitialized_copy(ranges::begin(__inr), return (*this)(ranges::begin(__inr),
ranges::end(__inr), ranges::end(__inr),
ranges::begin(__outr), ranges::begin(__outr),
ranges::end(__outr)); ranges::end(__outr));
} }
};
inline constexpr __uninitialized_copy_fn uninitialized_copy{};
template<typename _Iter, typename _Out> template<typename _Iter, typename _Out>
using uninitialized_copy_n_result = uninitialized_copy_result<_Iter, _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, template<input_iterator _Iter, __detail::__nothrow_forward_iterator _Out,
__detail::__nothrow_sentinel<_Out> _Sent> __detail::__nothrow_sentinel<_Out> _Sent>
requires constructible_from<iter_value_t<_Out>, iter_reference_t<_Iter>> requires constructible_from<iter_value_t<_Out>, iter_reference_t<_Iter>>
uninitialized_copy_n_result<_Iter, _Out> uninitialized_copy_n_result<_Iter, _Out>
uninitialized_copy_n(_Iter __ifirst, iter_difference_t<_Iter> __n, operator()(_Iter __ifirst, iter_difference_t<_Iter> __n,
_Out __ofirst, _Sent __olast) _Out __ofirst, _Sent __olast) const
{ {
using _OutType = remove_reference_t<iter_reference_t<_Out>>; using _OutType = remove_reference_t<iter_reference_t<_Out>>;
if constexpr (sized_sentinel_for<_Sent, _Out> if constexpr (sized_sentinel_for<_Sent, _Out>
&& is_trivial_v<_OutType> && is_trivial_v<_OutType>
&& is_nothrow_assignable_v<_OutType, && is_nothrow_assignable_v<_OutType,
iter_reference_t<_Iter>>) iter_reference_t<_Iter>>)
{ {
auto __d = ranges::distance(__ofirst, __olast); auto __d = ranges::distance(__ofirst, __olast);
return ranges::copy_n(__ifirst, std::min(__n, __d), __ofirst); return ranges::copy_n(__ifirst, std::min(__n, __d), __ofirst);
} }
else else
{ {
auto __guard = __detail::_DestroyGuard(&__ofirst); auto __guard = __detail::_DestroyGuard(&__ofirst);
for (; __n > 0 && __ofirst != __olast; for (; __n > 0 && __ofirst != __olast;
++__ofirst, (void)++__ifirst, (void)--__n) ++__ofirst, (void)++__ifirst, (void)--__n)
::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst);
__guard.release(); __guard.release();
return {__ifirst, __ofirst}; return {__ifirst, __ofirst};
} }
} }
};
inline constexpr __uninitialized_copy_n_fn uninitialized_copy_n{};
template<typename _Iter, typename _Out> template<typename _Iter, typename _Out>
using uninitialized_move_result = uninitialized_copy_result<_Iter, _Out>; using uninitialized_move_result = uninitialized_copy_result<_Iter, _Out>;
template<input_iterator _Iter, sentinel_for<_Iter> _ISent, struct __uninitialized_move_fn
__detail::__nothrow_forward_iterator _Out, {
__detail::__nothrow_sentinel<_Out> _OSent> template<input_iterator _Iter, sentinel_for<_Iter> _ISent,
requires constructible_from<iter_value_t<_Out>, __detail::__nothrow_forward_iterator _Out,
iter_rvalue_reference_t<_Iter>> __detail::__nothrow_sentinel<_Out> _OSent>
uninitialized_move_result<_Iter, _Out> requires constructible_from<iter_value_t<_Out>,
uninitialized_move(_Iter __ifirst, _ISent __ilast, iter_rvalue_reference_t<_Iter>>
_Out __ofirst, _OSent __olast) uninitialized_move_result<_Iter, _Out>
{ operator()(_Iter __ifirst, _ISent __ilast,
using _OutType = remove_reference_t<iter_reference_t<_Out>>; _Out __ofirst, _OSent __olast) const
if constexpr (sized_sentinel_for<_ISent, _Iter> {
&& sized_sentinel_for<_OSent, _Out> using _OutType = remove_reference_t<iter_reference_t<_Out>>;
&& is_trivial_v<_OutType> if constexpr (sized_sentinel_for<_ISent, _Iter>
&& is_nothrow_assignable_v<_OutType, && sized_sentinel_for<_OSent, _Out>
iter_rvalue_reference_t<_Iter>>) && is_trivial_v<_OutType>
{ && is_nothrow_assignable_v<_OutType,
auto __d1 = ranges::distance(__ifirst, __ilast); iter_rvalue_reference_t<_Iter>>)
auto __d2 = ranges::distance(__ofirst, __olast); {
return ranges::copy_n(std::make_move_iterator(__ifirst), auto __d1 = ranges::distance(__ifirst, __ilast);
std::min(__d1, __d2), __ofirst); auto __d2 = ranges::distance(__ofirst, __olast);
} return ranges::copy_n(std::make_move_iterator(__ifirst),
else std::min(__d1, __d2), __ofirst);
{ }
auto __guard = __detail::_DestroyGuard(&__ofirst); else
for (; __ifirst != __ilast && __ofirst != __olast; {
++__ofirst, (void)++__ifirst) auto __guard = __detail::_DestroyGuard(&__ofirst);
::new (__detail::__voidify(*__ofirst)) for (; __ifirst != __ilast && __ofirst != __olast;
_OutType(ranges::iter_move(__ifirst)); ++__ofirst, (void)++__ifirst)
__guard.release(); ::new (__detail::__voidify(*__ofirst))
return {__ifirst, __ofirst}; _OutType(ranges::iter_move(__ifirst));
} __guard.release();
} return {__ifirst, __ofirst};
}
}
template<input_range _IRange, __detail::__nothrow_forward_range _ORange> template<input_range _IRange, __detail::__nothrow_forward_range _ORange>
requires constructible_from<range_value_t<_ORange>, requires constructible_from<range_value_t<_ORange>,
range_rvalue_reference_t<_IRange>> range_rvalue_reference_t<_IRange>>
uninitialized_move_result<safe_iterator_t<_IRange>, uninitialized_move_result<safe_iterator_t<_IRange>,
safe_iterator_t<_ORange>> safe_iterator_t<_ORange>>
uninitialized_move(_IRange&& __inr, _ORange&& __outr) operator()(_IRange&& __inr, _ORange&& __outr) const
{ {
return ranges::uninitialized_move(ranges::begin(__inr), return (*this)(ranges::begin(__inr),
ranges::end(__inr), ranges::end(__inr),
ranges::begin(__outr), ranges::begin(__outr),
ranges::end(__outr)); ranges::end(__outr));
} }
};
inline constexpr __uninitialized_move_fn uninitialized_move{};
template<typename _Iter, typename _Out> template<typename _Iter, typename _Out>
using uninitialized_move_n_result = uninitialized_copy_result<_Iter, _Out>; using uninitialized_move_n_result = uninitialized_copy_result<_Iter, _Out>;
template<input_iterator _Iter, __detail::__nothrow_forward_iterator _Out, struct __uninitialized_move_n_fn
__detail::__nothrow_sentinel<_Out> _Sent> {
requires constructible_from<iter_value_t<_Out>, template<input_iterator _Iter, __detail::__nothrow_forward_iterator _Out,
iter_rvalue_reference_t<_Iter>> __detail::__nothrow_sentinel<_Out> _Sent>
uninitialized_move_n_result<_Iter, _Out> requires constructible_from<iter_value_t<_Out>,
uninitialized_move_n(_Iter __ifirst, iter_difference_t<_Iter> __n, iter_rvalue_reference_t<_Iter>>
_Out __ofirst, _Sent __olast) uninitialized_move_n_result<_Iter, _Out>
{ operator()(_Iter __ifirst, iter_difference_t<_Iter> __n,
using _OutType = remove_reference_t<iter_reference_t<_Out>>; _Out __ofirst, _Sent __olast) const
if constexpr (sized_sentinel_for<_Sent, _Out> {
&& is_trivial_v<_OutType> using _OutType = remove_reference_t<iter_reference_t<_Out>>;
&& is_nothrow_assignable_v<_OutType, if constexpr (sized_sentinel_for<_Sent, _Out>
iter_rvalue_reference_t<_Iter>>) && is_trivial_v<_OutType>
{ && is_nothrow_assignable_v<_OutType,
auto __d = ranges::distance(__ofirst, __olast); iter_rvalue_reference_t<_Iter>>)
return ranges::copy_n(std::make_move_iterator(__ifirst), {
std::min(__n, __d), __ofirst); auto __d = ranges::distance(__ofirst, __olast);
} return ranges::copy_n(std::make_move_iterator(__ifirst),
else std::min(__n, __d), __ofirst);
{ }
auto __guard = __detail::_DestroyGuard(&__ofirst); else
for (; __n > 0 && __ofirst != __olast; {
++__ofirst, (void)++__ifirst, (void)--__n) auto __guard = __detail::_DestroyGuard(&__ofirst);
::new (__detail::__voidify(*__ofirst)) for (; __n > 0 && __ofirst != __olast;
_OutType(ranges::iter_move(__ifirst)); ++__ofirst, (void)++__ifirst, (void)--__n)
__guard.release(); ::new (__detail::__voidify(*__ofirst))
return {__ifirst, __ofirst}; _OutType(ranges::iter_move(__ifirst));
} __guard.release();
} return {__ifirst, __ofirst};
}
}
};
template<__detail::__nothrow_forward_iterator _Iter, inline constexpr __uninitialized_move_n_fn uninitialized_move_n{};
__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;
}
}
template<__detail::__nothrow_forward_range _Range, typename _Tp> struct __uninitialized_fill_fn
requires constructible_from<range_value_t<_Range>, const _Tp&> {
safe_iterator_t<_Range> template<__detail::__nothrow_forward_iterator _Iter,
uninitialized_fill(_Range&& __r, const _Tp& __x) __detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp>
{ requires constructible_from<iter_value_t<_Iter>, const _Tp&>
return ranges::uninitialized_fill(ranges::begin(__r), ranges::end(__r), _Iter
__x); 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> template<__detail::__nothrow_forward_range _Range, typename _Tp>
requires constructible_from<iter_value_t<_Iter>, const _Tp&> requires constructible_from<range_value_t<_Range>, const _Tp&>
_Iter safe_iterator_t<_Range>
uninitialized_fill_n(_Iter __first, iter_difference_t<_Iter> __n, operator()(_Range&& __r, const _Tp& __x) const
const _Tp& __x) {
{ return (*this)(ranges::begin(__r), ranges::end(__r),
using _ValueType = remove_reference_t<iter_reference_t<_Iter>>; __x);
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<typename _Tp, typename... _Args> inline constexpr __uninitialized_fill_fn uninitialized_fill{};
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)...);
}
template<destructible _Tp> struct __uninitialized_fill_n_fn
constexpr void {
destroy_at(_Tp* __location) noexcept template<__detail::__nothrow_forward_iterator _Iter, typename _Tp>
{ requires constructible_from<iter_value_t<_Iter>, const _Tp&>
if constexpr (is_array_v<_Tp>) _Iter
ranges::destroy(ranges::begin(*__location), ranges::end(*__location)); operator()(_Iter __first, iter_difference_t<_Iter> __n,
else const _Tp& __x) const
__location->~_Tp(); {
} 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, template<__detail::__nothrow_input_iterator _Iter,
__detail::__nothrow_sentinel<_Iter> _Sent> __detail::__nothrow_sentinel<_Iter> _Sent>
requires destructible<iter_value_t<_Iter>> requires destructible<iter_value_t<_Iter>>
constexpr _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>>) if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>)
return ranges::next(__first, __last); return ranges::next(__first, __last);
...@@ -466,23 +540,28 @@ namespace ranges ...@@ -466,23 +540,28 @@ namespace ranges
template<__detail::__nothrow_input_range _Range> template<__detail::__nothrow_input_range _Range>
requires destructible<range_value_t<_Range>> requires destructible<range_value_t<_Range>>
constexpr safe_iterator_t<_Range> constexpr safe_iterator_t<_Range>
destroy(_Range&& __r) noexcept __destroy_fn::operator()(_Range&& __r) const noexcept
{ return ranges::destroy(ranges::begin(__r), ranges::end(__r)); } { return (*this)(ranges::begin(__r), ranges::end(__r)); }
template<__detail::__nothrow_input_iterator _Iter> struct __destroy_n_fn
requires destructible<iter_value_t<_Iter>> {
constexpr _Iter template<__detail::__nothrow_input_iterator _Iter>
destroy_n(_Iter __first, iter_difference_t<_Iter> __n) noexcept requires destructible<iter_value_t<_Iter>>
{ constexpr _Iter
if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>) operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept
return ranges::next(__first, __n); {
else if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>)
{ return ranges::next(__first, __n);
for (; __n > 0; ++__first, (void)--__n) else
ranges::destroy_at(std::__addressof(*__first)); {
return __first; 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 _GLIBCXX_END_NAMESPACE_VERSION
} // namespace std } // namespace std
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment