Hi,

This is v2 of my generators patch.  It addresses Jonathans review
comments, but does not add more tests yet :-/

Original series:
https://inbox.sourceware.org/20231118195008.579211-1-ar...@aarsen.me/

Changes since v1:
- Uglify some symbols
- Convert _Is_generator concept to __is_generator CE bool
- Add "libstdc++: add missing include in ranges_util.h" - this can be
  pushed separately, really, but I forgot to send it.

Range-diff:

1:  feab374887e5 = 1212:  c4286af0c70f libstdc++: add missing include in 
ranges_util.h
2:  010eab271755 ! 1213:  fb589641656f libstdc++: implement std::generator
 @@ libstdc++-v3/include/std/generator (new)
  +#define __glibcxx_want_generator
  +#include <bits/version.h>
  +
 -+#if __cplusplus < 202302L
 -+# error "std::generator is a C++23 extension"
 -+#endif
 -+
  +#ifdef __cpp_lib_generator  // C++ >= 23 && __glibcxx_coroutine
  +#include <new>
  +#include <bits/move.h>
 @@ libstdc++-v3/include/std/generator (new)
  +  {
  +    /// _Reference type for a generator whose reference (first argument) and
  +    /// value (second argument) types are _Ref and _V.
 -+    template<typename _Ref, typename _V>
 -+    using _Reference_t = __conditional_t<is_void_v<_V>,
 ++    template<typename _Ref, typename _Val>
 ++    using _Reference_t = __conditional_t<is_void_v<_Val>,
  +                                     _Ref&&, _Ref>;
  +
  +    /// Type yielded by a generator whose _Reference type is _Reference.
 @@ libstdc++-v3/include/std/generator (new)
  +                                 const _Reference&>;
  +
  +    /// _Yield_t * _Reference_t
 -+    template<typename _Ref, typename _V>
 -+    using _Yield2_t = _Yield_t<_Reference_t<_Ref, _V>>;
 -+
 -+    template<typename> struct _Is_generator_t : std::false_type {};
 -+    template<typename _V, typename _R, typename _A>
 -+      struct _Is_generator_t<::std::generator<_V, _R, _A>> : std::true_type 
{};
 -+
 -+    template<typename _T>
 -+    concept _Is_generator = _Is_generator_t<remove_cvref_t<_T>>::value;
 ++    template<typename _Ref, typename _Val>
 ++    using _Yield2_t = _Yield_t<_Reference_t<_Ref, _Val>>;
  +
 ++    template<typename> constexpr bool __is_generator = false;
 ++    template<typename _Val, typename _Ref, typename _Alloc>
 ++    constexpr bool __is_generator<std::generator<_Val, _Ref, _Alloc>> = true;
  +
  +    /// Allocator and value type erased generator promise type.
  +    /// \tparam _Yielded The corresponding generators yielded type.
 @@ libstdc++-v3/include/std/generator (new)
  +     using _Coro_handle = std::coroutine_handle<_Promise_erased>;
  +
  +     template<typename, typename, typename>
 -+     friend struct std::generator;
 ++     friend class std::generator;
  +
  +     template<typename _Gen>
  +      struct _Recursive_awaiter;
 @@ libstdc++-v3/include/std/generator (new)
  +      __rn._M_top() = __new;
  +
  +      // Presume we're the second frame...
 -+      auto& __bott = __rest;
 ++      auto __bott = __rest;
  +      if (auto __f = std::get_if<_Frame>(&__rn._M_stack))
  +        // But, if we aren't, get the actual bottom.  We're only the second
  +        // frame if our parent is the bottom frame, i.e. it doesn't have a
 @@ libstdc++-v3/include/std/generator (new)
  +      struct _Promise_erased<_Yielded>::_Recursive_awaiter
  +      {
  +     _Gen _M_gen;
 -+     static_assert(_Is_generator<_Gen>);
 ++     static_assert(__is_generator<_Gen>);
  +     static_assert(std::same_as<typename _Gen::yielded, _Yielded>);
  +
  +     _Recursive_awaiter(_Gen __gen) noexcept
 @@ libstdc++-v3/include/std/generator (new)
  +      requires default_initializable<_Rebound> // _Alloc is non-void
  +     { return _M_allocate({}, __sz); }
  +
 -+     template<typename _NA, typename... _Args>
 ++     template<typename _Na, typename... _Args>
  +     void*
  +     operator new(std::size_t __sz,
 -+                 allocator_arg_t, const _NA& __na,
 ++                 allocator_arg_t, const _Na& __na,
  +                 const _Args&...)
 -+      requires convertible_to<const _NA&, _Alloc>
 ++      requires convertible_to<const _Na&, _Alloc>
  +     {
  +      return _M_allocate(static_cast<_Rebound>(static_cast<_Alloc>(__na)),
  +                         __sz);
  +     }
  +
 -+     template<typename _This, typename _NA, typename... _Args>
 ++     template<typename _This, typename _Na, typename... _Args>
  +     void*
  +     operator new(std::size_t __sz,
  +                 const _This&,
 -+                 allocator_arg_t, const _NA& __na,
 ++                 allocator_arg_t, const _Na& __na,
  +                 const _Args&...)
 -+      requires convertible_to<const _NA&, _Alloc>
 ++      requires convertible_to<const _Na&, _Alloc>
  +     {
  +      return _M_allocate(static_cast<_Rebound>(static_cast<_Alloc>(__na)),
  +                         __sz);
 @@ libstdc++-v3/include/std/generator (new)
  +        }
  +     }
  +
 -+     template<typename _NA>
 ++     template<typename _Na>
  +     static void*
 -+     _M_allocate(const _NA& __na, std::size_t __csz)
 ++     _M_allocate(const _Na& __na, std::size_t __csz)
  +     {
 -+      using _Rebound = typename std::allocator_traits<_NA>
 ++      using _Rebound = typename std::allocator_traits<_Na>
  +        ::template rebind_alloc<_Alloc_block>;
 -+      using _Rebound_ATr = typename std::allocator_traits<_NA>
 ++      using _Rebound_ATr = typename std::allocator_traits<_Na>
  +        ::template rebind_traits<_Alloc_block>;
  +
  +      static_assert(is_pointer_v<typename _Rebound_ATr::pointer>,
 @@ libstdc++-v3/include/std/generator (new)
  +      return __p;
  +     }
  +
 -+     template<typename _NA, typename... _Args>
 ++     template<typename _Na, typename... _Args>
  +     void*
  +     operator new(std::size_t __sz,
 -+                 allocator_arg_t, const _NA& __na,
 ++                 allocator_arg_t, const _Na& __na,
  +                 const _Args&...)
  +     { return _M_allocate(__na, __sz); }
  +
 -+     template<typename _This, typename _NA, typename... _Args>
 ++     template<typename _This, typename _Na, typename... _Args>
  +     void*
  +     operator new(std::size_t __sz,
  +                 const _This&,
 -+                 allocator_arg_t, const _NA& __na,
 ++                 allocator_arg_t, const _Na& __na,
  +                 const _Args&...)
  +     { return _M_allocate(__na, __sz); }
  +
 @@ libstdc++-v3/include/std/generator (new)
  +     }
  +      };
  +
 -+    template<typename _T>
 -+    concept _Cv_unqualified_object = is_object_v<_T>
 -+      && same_as<_T, remove_cv_t<_T>>;
 ++    template<typename _Tp>
 ++    concept _Cv_unqualified_object = is_object_v<_Tp>
 ++      && same_as<_Tp, remove_cv_t<_Tp>>;
  +  } // namespace __gen
  +  /// @endcond
  +
 @@ libstdc++-v3/include/std/generator (new)
  +      using difference_type = ptrdiff_t;
  +
  +      friend bool
 -+      operator==(const _Iterator& i, default_sentinel_t) noexcept
 -+      { return i._M_coro.done(); }
 ++      operator==(const _Iterator& __i, default_sentinel_t) noexcept
 ++      { return __i._M_coro.done(); }
  +
  +      friend class generator;
  +
 @@ libstdc++-v3/include/std/generator (new)
  +
  +#if _GLIBCXX_HOSTED
  +  namespace pmr {
 -+    template<class R, class V = void>
 -+    using generator = std::generator<R, V, polymorphic_allocator<std::byte>>;
 ++    template<typename _Ref, typename _Val = void>
 ++    using generator = std::generator<_Ref, _Val, 
polymorphic_allocator<std::byte>>;
  +  }
  +#endif // HOSTED
  +

Tested libstdc++ on x86_64-pc-linux-gnu.

TIA, have a lovely day.

Arsen Arsenović (2):
  libstdc++: add missing include in ranges_util.h
  libstdc++: implement std::generator

 libstdc++-v3/include/Makefile.am              |   2 +
 libstdc++-v3/include/Makefile.in              |   2 +
 libstdc++-v3/include/bits/elements_of.h       |  72 ++
 libstdc++-v3/include/bits/ranges_util.h       |   1 +
 libstdc++-v3/include/bits/version.def         |   9 +
 libstdc++-v3/include/bits/version.h           |  11 +
 libstdc++-v3/include/precompiled/stdc++.h     |   1 +
 libstdc++-v3/include/std/generator            | 812 ++++++++++++++++++
 libstdc++-v3/include/std/ranges               |   4 +
 .../24_iterators/range_generators/01.cc       |  55 ++
 .../24_iterators/range_generators/02.cc       | 219 +++++
 .../24_iterators/range_generators/copy.cc     |  97 +++
 .../24_iterators/range_generators/except.cc   |  97 +++
 .../24_iterators/range_generators/subrange.cc |  45 +
 .../24_iterators/range_generators/synopsis.cc |  38 +
 15 files changed, 1465 insertions(+)
 create mode 100644 libstdc++-v3/include/bits/elements_of.h
 create mode 100644 libstdc++-v3/include/std/generator
 create mode 100644 libstdc++-v3/testsuite/24_iterators/range_generators/01.cc
 create mode 100644 libstdc++-v3/testsuite/24_iterators/range_generators/02.cc
 create mode 100644 libstdc++-v3/testsuite/24_iterators/range_generators/copy.cc
 create mode 100644 
libstdc++-v3/testsuite/24_iterators/range_generators/except.cc
 create mode 100644 
libstdc++-v3/testsuite/24_iterators/range_generators/subrange.cc
 create mode 100644 
libstdc++-v3/testsuite/24_iterators/range_generators/synopsis.cc

-- 
2.43.0

Reply via email to