When I remove <bits/stl_algobase.h> for importing __memcmp (my apologies for writing __memcpy) from libstdc++-v3/include/bits/ranges_algobase.h and try to rerun the code, I get the following error:
In file included from $HOME/projects/objdirforgcc/_pfx/include/c++/15.0.0/numeric:69, from ranges-iota-fix.cpp:1: $HOME/projects/objdirforgcc/_pfx/include/c++/15.0.0/bits/ranges_algobase.h: In member function ‘constexpr bool std::ranges::__equal_fn::operator()(_Iter1, _Sent1, _Iter2, _Sent2, _Pred, _Proj1, _Proj2) const’: $HOME/projects/objdirforgcc/_pfx/include/c++/15.0.0/bits/ranges_algobase.h:143:32: error: ‘__memcmp’ is not a member of ‘std’; did you mean ‘__memcmpable’? 143 | return !std::__memcmp(__first1, __first2, __len); | ^~~~~~~~ | __memcmpable From: jwak...@redhat.com At: 05/24/24 10:12:57 UTC-4:00To: Michael Levine (BLOOMBERG/ 731 LEX ) Cc: ppa...@redhat.com, gcc-patches@gcc.gnu.org, libstd...@gcc.gnu.org Subject: Re: [PATCH v3] libstdc++: Fix std::ranges::iota not in numeric [PR108760] On 24/05/24 13:56 -0000, Michael Levine (BLOOMBERG/ 731 LEX) wrote: >I've attached the v3 version of the patch as a single, squashed patch containing all of the changes. I manually prepended my sign off to the patch. >Signed-off-by: Michael Levine <mlevin...@bloomberg.net> >--- >diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h >index 62faff173bd..d258be0b93f 100644 >--- a/libstdc++-v3/include/bits/ranges_algo.h >+++ b/libstdc++-v3/include/bits/ranges_algo.h >@@ -3521,58 +3521,6 @@ namespace ranges > > #endif // __glibcxx_ranges_contains > >-#if __glibcxx_ranges_iota >= 202202L // C++ >= 23 >- >- 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{}; >- >-#endif // __glibcxx_ranges_iota >- > #if __glibcxx_ranges_find_last >= 202207L // C++ >= 23 > > struct __find_last_fn >diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h >index e26a73a27d6..965b36aed35 100644 >--- a/libstdc++-v3/include/bits/ranges_algobase.h >+++ b/libstdc++-v3/include/bits/ranges_algobase.h >@@ -35,6 +35,7 @@ > #include <compare> > #include <bits/stl_iterator_base_funcs.h> > #include <bits/stl_iterator.h> >+#include <bits/stl_algobase.h> // __memcpy Why is this being added here? What is __memcpy? I don't think out_value_result requires any new headers to be included here, does it? > #include <bits/ranges_base.h> // ranges::begin, ranges::range etc. > #include <bits/invoke.h> // __invoke > #include <bits/cpp_type_traits.h> // __is_byte >@@ -70,6 +71,32 @@ namespace ranges > __is_move_iterator<move_iterator<_Iterator>> = true; > } // namespace __detail > >+#if __glibcxx_ranges_iota >= 202202L // C++ >= 23 >+ >+ 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)}; } >+ }; >+ >+#endif // __glibcxx_ranges_iota >+ >+ > struct __equal_fn > { > template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1, >diff --git a/libstdc++-v3/include/std/numeric b/libstdc++-v3/include/std/numeric >index c912db4a519..d88f7f02137 100644 >--- a/libstdc++-v3/include/std/numeric >+++ b/libstdc++-v3/include/std/numeric >@@ -65,6 +65,10 @@ > # include <parallel/numeric> > #endif > >+#if __glibcxx_ranges_iota >= 202202L // C++ >= 23 >+#include <bits/ranges_algobase.h> // for out_value_result as used by std::ranges::iota. It transitively also brings in <bits/ranges_base.h>, from which _Range is used by std::ranges::iota We generally try to keep lines below 80 columns, or 120 at a push. This is unnecessarily long, and I don't know what _Range is meant to be (that's just a template parameter, not something defined in <bits/ranges_algobase.h>. Please just use: #include <bits/ranges_algobase.h> // for ranges::out_value_result Otherwise this looks ready to go in, thanks. >+#endif // __glibcxx_ranges_iota >+ > #if __cplusplus >= 201402L > # include <type_traits> > # include <bit> >@@ -726,6 +730,40 @@ namespace __detail > /// @} group numeric_ops > #endif // C++17 > >+namespace ranges >+{ >+#if __glibcxx_ranges_iota >= 202202L // C++ >= 23 >+ >+ 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 // __glibcxx_ranges_iota >+} // namespace ranges >+ > _GLIBCXX_END_NAMESPACE_VERSION > } // namespace std > >diff --git a/libstdc++-v3/testsuite/25_algorithms/iota/1.cc b/libstdc++-v3/testsuite/26_numerics/iota/2.cc >similarity index 96% >rename from libstdc++-v3/testsuite/25_algorithms/iota/1.cc >rename to libstdc++-v3/testsuite/26_numerics/iota/2.cc >index 61bf418b4da..040c48d91ce 100644 >--- a/libstdc++-v3/testsuite/25_algorithms/iota/1.cc >+++ b/libstdc++-v3/testsuite/26_numerics/iota/2.cc >@@ -1,6 +1,6 @@ > // { dg-do run { target c++23 } } > >-#include <algorithm> >+#include <numeric> > #include <testsuite_hooks.h> > #include <testsuite_iterators.h> >