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:
Patrick Palka 2020-02-13 12:17:01 -05:00
parent 90b7eb6539
commit b40c57bdd2
4 changed files with 3722 additions and 3212 deletions

View File

@ -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

View File

@ -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

View File

@ -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