libstdc++: Fix std::ranges::iota is not included in numeric [PR108760]

Before this patch, using std::ranges::iota required including
<algorithm> when it should have been sufficient to only include
<numeric>.

For the backport to the release branch ranges::iota is defined in
<bits/ranges_algobase.h> so that it's available in both <numeric> and
<algorithm>. This avoids breaking code that compiles successfully using
existing releases where <algorithm> defines ranges::iota.

libstdc++-v3/ChangeLog:

	PR libstdc++/108760
	* include/bits/ranges_algo.h (ranges::out_value_result)
	(ranges::iota_result, ranges::__iota_fn, ranges::iota): Move to
	<bits/ranges_algobase.h>.
	* include/bits/ranges_algobase.h (ranges::out_value_result):
	(ranges::iota_result, ranges::__iota_fn, ranges::iota): Move to
	here.
	* include/std/numeric: Include <bits/ranges_algobase.h>.
	* testsuite/25_algorithms/iota/1.cc: Renamed to ...
	* testsuite/26_numerics/iota/2.cc: ... here.

Signed-off-by: Michael Levine <mlevine55@bloomberg.net>
(cherry picked from commit 0bb1db32cc)
This commit is contained in:
Michael Levine 2024-06-07 09:54:38 +01:00 committed by Jonathan Wakely
parent 285f01004e
commit 997d51f3dc
4 changed files with 57 additions and 51 deletions

View File

@ -3524,56 +3524,6 @@ namespace ranges
inline constexpr __contains_subrange_fn contains_subrange{};
#define __cpp_lib_ranges_iota 202202L
template<typename _Out, typename _Tp>
struct out_value_result
{
[[no_unique_address]] _Out out;
[[no_unique_address]] _Tp value;
template<typename _Out2, typename _Tp2>
requires convertible_to<const _Out&, _Out2>
&& convertible_to<const _Tp&, _Tp2>
constexpr
operator out_value_result<_Out2, _Tp2>() const &
{ return {out, value}; }
template<typename _Out2, typename _Tp2>
requires convertible_to<_Out, _Out2>
&& convertible_to<_Tp, _Tp2>
constexpr
operator out_value_result<_Out2, _Tp2>() &&
{ return {std::move(out), std::move(value)}; }
};
template<typename _Out, typename _Tp>
using iota_result = out_value_result<_Out, _Tp>;
struct __iota_fn
{
template<input_or_output_iterator _Out, sentinel_for<_Out> _Sent, weakly_incrementable _Tp>
requires indirectly_writable<_Out, const _Tp&>
constexpr iota_result<_Out, _Tp>
operator()(_Out __first, _Sent __last, _Tp __value) const
{
while (__first != __last)
{
*__first = static_cast<const _Tp&>(__value);
++__first;
++__value;
}
return {std::move(__first), std::move(__value)};
}
template<weakly_incrementable _Tp, output_range<const _Tp&> _Range>
constexpr iota_result<borrowed_iterator_t<_Range>, _Tp>
operator()(_Range&& __r, _Tp __value) const
{ return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__value)); }
};
inline constexpr __iota_fn iota{};
#define __cpp_lib_ranges_find_last 202207L
struct __find_last_fn

View File

@ -71,6 +71,58 @@ namespace ranges
__is_move_iterator<move_iterator<_Iterator>> = true;
} // namespace __detail
#if __cplusplus > 202002L
template<typename _Out, typename _Tp>
struct out_value_result
{
[[no_unique_address]] _Out out;
[[no_unique_address]] _Tp value;
template<typename _Out2, typename _Tp2>
requires convertible_to<const _Out&, _Out2>
&& convertible_to<const _Tp&, _Tp2>
constexpr
operator out_value_result<_Out2, _Tp2>() const &
{ return {out, value}; }
template<typename _Out2, typename _Tp2>
requires convertible_to<_Out, _Out2>
&& convertible_to<_Tp, _Tp2>
constexpr
operator out_value_result<_Out2, _Tp2>() &&
{ return {std::move(out), std::move(value)}; }
};
#define __cpp_lib_ranges_iota 202202L
template<typename _Out, typename _Tp>
using iota_result = out_value_result<_Out, _Tp>;
struct __iota_fn
{
template<input_or_output_iterator _Out, sentinel_for<_Out> _Sent, weakly_incrementable _Tp>
requires indirectly_writable<_Out, const _Tp&>
constexpr iota_result<_Out, _Tp>
operator()(_Out __first, _Sent __last, _Tp __value) const
{
while (__first != __last)
{
*__first = static_cast<const _Tp&>(__value);
++__first;
++__value;
}
return {std::move(__first), std::move(__value)};
}
template<weakly_incrementable _Tp, output_range<const _Tp&> _Range>
constexpr iota_result<borrowed_iterator_t<_Range>, _Tp>
operator()(_Range&& __r, _Tp __value) const
{ return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__value)); }
};
inline constexpr __iota_fn iota{};
#endif // C++23
struct __equal_fn
{
template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,

View File

@ -79,6 +79,10 @@
# include <limits>
#endif
#if __cplusplus > 202002L
# include <bits/ranges_algobase.h> // for ranges::iota
#endif
/**
* @defgroup numerics Numerics
*

View File

@ -1,7 +1,7 @@
// { dg-options "-std=gnu++23" }
// { dg-do run { target c++23 } }
#include <algorithm>
#include <numeric>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>