To test the theory that this issue was unrelated to my patch, I moved the 
out_value_result definition into std/numeric and restored the version of 
bits/ranges_algobase.h to the version in master.  I kept the include line 
"include <bits/ranges_algobase.h>" in std/numeric even though it wasn't being 
used.  With the include line I see the same error about __memcmp is not a 
member of 'std'. 

From: Michael Levine (BLOOMBERG/ 731 LEX) At: 05/30/24 13:43:58 UTC-4:00To:  
jwak...@redhat.com
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]
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>
> 


Reply via email to