Skip to content

Conversation

@anonymouspc
Copy link
Contributor

This PR implements std::ranges::chunk_view and std::views::chunk in header <__ranges/chunk_view.h>.

This is partial P2242R1 (as P2242R1 contains both views::chunk and views::slide).

Thank you!

@anonymouspc anonymouspc requested a review from a team as a code owner December 8, 2025 23:59
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Dec 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 9, 2025

@llvm/pr-subscribers-libcxx

Author: anonymous (anonymouspc)

Changes

This PR implements std::ranges::chunk_view and std::views::chunk in header <__ranges/chunk_view.h>.

This is partial P2242R1 (as P2242R1 contains both views::chunk and views::slide).

Thank you!


Patch is 42.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/171232.diff

18 Files Affected:

  • (modified) libcxx/docs/FeatureTestMacroTable.rst (+1-1)
  • (modified) libcxx/docs/ReleaseNotes/22.rst (+1)
  • (modified) libcxx/docs/Status/Cxx23Papers.csv (+2-2)
  • (modified) libcxx/include/CMakeLists.txt (+1)
  • (modified) libcxx/include/__cxx03/module.modulemap (+1)
  • (added) libcxx/include/__ranges/chunk_view.h (+543)
  • (modified) libcxx/include/module.modulemap.in (+4)
  • (modified) libcxx/include/ranges (+12)
  • (modified) libcxx/modules/std/ranges.inc (+4-2)
  • (added) libcxx/test/std/ranges/range.adaptors/range.chunk/adaptor.pass.cpp (+73)
  • (added) libcxx/test/std/ranges/range.adaptors/range.chunk/base.pass.cpp (+41)
  • (added) libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp (+63)
  • (added) libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp (+48)
  • (added) libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp (+64)
  • (added) libcxx/test/std/ranges/range.adaptors/range.chunk/general.pass.cpp (+47)
  • (added) libcxx/test/std/ranges/range.adaptors/range.chunk/types.h (+64)
  • (modified) libcxx/utils/generate_feature_test_macro_components.py (-1)
  • (modified) llvm/utils/gn/secondary/libcxx/include/BUILD.gn (+1)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 756bdf71f8b22..49672e5ccf70a 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -370,7 +370,7 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_ranges_as_rvalue``                             ``202207L``
     ---------------------------------------------------------- -----------------
-    ``__cpp_lib_ranges_chunk``                                 *unimplemented*
+    ``__cpp_lib_ranges_chunk``                                 ``202202L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_ranges_chunk_by``                              ``202202L``
     ---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 9f1e3d570f254..4c0f5b34abcaf 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -49,6 +49,7 @@ Implemented Papers
 - P2835R7: Expose ``std::atomic_ref``'s object address (`Github <https://llvm.org/PR118377>`__)
 - P2944R3: Comparisons for ``reference_wrapper`` (`Github <https://llvm.org/PR105424>`__)
 - P3168R2: Give ``std::optional`` Range Support (`Github <https://llvm.org/PR105430>`__)
+- P2442R1: Add ``std::views::chunk`` (`Github <https://llvm.org/PR171109>`__)
 
 Improvements and New Features
 -----------------------------
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index b655384bad7f2..46327b0a82353 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -48,8 +48,8 @@
 "`P2387R3 <https://wg21.link/P2387R3>`__","Pipe support for user-defined range adaptors","2022-02 (Virtual)","|Complete|","19","`#105183 <https://github.com/llvm/llvm-project/issues/105183>`__",""
 "`P2440R1 <https://wg21.link/P2440R1>`__","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","2022-02 (Virtual)","|Partial|","","`#105184 <https://github.com/llvm/llvm-project/issues/105184>`__","Only ``ranges::iota`` is implemented."
 "`P2441R2 <https://wg21.link/P2441R2>`__","``views::join_with``","2022-02 (Virtual)","|Complete|","21","`#105185 <https://github.com/llvm/llvm-project/issues/105185>`__",""
-"`P2442R1 <https://wg21.link/P2442R1>`__","Windowing range adaptors: ``views::chunk`` and ``views::slide``","2022-02 (Virtual)","","","`#105187 <https://github.com/llvm/llvm-project/issues/105187>`__",""
-"`P2443R1 <https://wg21.link/P2443R1>`__","``views::chunk_by``","2022-02 (Virtual)","|Complete|","18","`#105188 <https://github.com/llvm/llvm-project/issues/105188>`__",""
+"`P2442R1 <https://wg21.link/P2442R1>`__","Windowing range adaptors: ``views::chunk`` and ``views::slide``","2022-02 (Virtual)","|Partial|","22","`#105187 <https://github.com/llvm/llvm-project/issues/105187>`__",""
+"`P2443R1 <https://wg21.link/P2443R1>`__","``views::chunk_by``","2022-02 (Virtual)","|Complete|","18","`#105188 <https://github.com/llvm/llvm-project/issues/105188>`__","Only ``views::chunk`` is implemented."
 "","","","","","",""
 "`P0009R18 <https://wg21.link/P0009R18>`__","mdspan: A Non-Owning Multidimensional Array Reference","2022-07 (Virtual)","|Complete|","18","`#105189 <https://github.com/llvm/llvm-project/issues/105189>`__",""
 "`P0429R9 <https://wg21.link/P0429R9>`__","A Standard ``flat_map``","2022-07 (Virtual)","|Complete|","20","`#105190 <https://github.com/llvm/llvm-project/issues/105190>`__",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index cbcd764e67d93..afe8391f1a5d5 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -703,6 +703,7 @@ set(files
   __ranges/all.h
   __ranges/as_rvalue_view.h
   __ranges/chunk_by_view.h
+  __ranges/chunk_view.h
   __ranges/common_view.h
   __ranges/concepts.h
   __ranges/container_compatible_range.h
diff --git a/libcxx/include/__cxx03/module.modulemap b/libcxx/include/__cxx03/module.modulemap
index 34a2d0f25fc45..b7eee575090ce 100644
--- a/libcxx/include/__cxx03/module.modulemap
+++ b/libcxx/include/__cxx03/module.modulemap
@@ -1701,6 +1701,7 @@ module cxx03_std_private_ranges_all                        [system] {
 }
 module cxx03_std_private_ranges_as_rvalue_view             [system] { header "__ranges/as_rvalue_view.h" }
 module cxx03_std_private_ranges_chunk_by_view              [system] { header "__ranges/chunk_by_view.h" }
+module cxx03_std_private_ranges_chunk_view                 [system] { header "__ranges/chunk_view.h" }
 module cxx03_std_private_ranges_common_view                [system] { header "__ranges/common_view.h" }
 module cxx03_std_private_ranges_concepts                   [system] {
   header "__ranges/concepts.h"
diff --git a/libcxx/include/__ranges/chunk_view.h b/libcxx/include/__ranges/chunk_view.h
new file mode 100644
index 0000000000000..b1c96223ae7c1
--- /dev/null
+++ b/libcxx/include/__ranges/chunk_view.h
@@ -0,0 +1,543 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___RANGES_CHUNK_VIEW_H
+#define _LIBCPP___RANGES_CHUNK_VIEW_H
+
+#include <__algorithm/ranges_min.h>
+#include <__assert>
+#include <__concepts/constructible.h>
+#include <__concepts/convertible_to.h>
+#include <__config>
+#include <__functional/bind_back.h>
+#include <__iterator/advance.h>
+#include <__iterator/concepts.h>
+#include <__iterator/default_sentinel.h>
+#include <__iterator/distance.h>
+#include <__iterator/iter_move.h>
+#include <__iterator/iter_swap.h>
+#include <__iterator/iterator_traits.h>
+#include <__memory/addressof.h>
+#include <__ranges/access.h>
+#include <__ranges/all.h>
+#include <__ranges/concepts.h>
+#include <__ranges/enable_borrowed_range.h>
+#include <__ranges/non_propagating_cache.h>
+#include <__ranges/range_adaptor.h>
+#include <__ranges/take_view.h>
+#include <__ranges/view_interface.h>
+#include <__type_traits/conditional.h>
+#include <__type_traits/decay.h>
+#include <__type_traits/is_nothrow_constructible.h>
+#include <__type_traits/make_unsigned.h>
+#include <__utility/forward.h>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+
+namespace ranges {
+
+template <class _Integral>
+inline _LIBCPP_HIDE_FROM_ABI constexpr auto __div_ceil(_Integral __num, _Integral __denom) {
+  _Integral __r = __num / __denom;
+  if (__num % __denom)
+    ++__r;
+  return __r;
+}
+
+template <view _View>
+  requires input_range<_View>
+class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS chunk_view : public view_interface<chunk_view<_View>> {
+  _LIBCPP_NO_UNIQUE_ADDRESS _View __base_;
+  _LIBCPP_NO_UNIQUE_ADDRESS range_difference_t<_View> __n_;
+  _LIBCPP_NO_UNIQUE_ADDRESS range_difference_t<_View> __remainder_;
+  _LIBCPP_NO_UNIQUE_ADDRESS __non_propagating_cache<iterator_t<_View>> __current_;
+
+  class __outer_iterator;
+  class __inner_iterator;
+
+public:
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit chunk_view(_View __base, range_difference_t<_View> __n)
+      : __base_(std::move(__base)), __n_(__n), __remainder_(0) {
+    _LIBCPP_ASSERT_PEDANTIC(__n > 0, "Trying to construct a chunk_view with chunk size <= 0");
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
+    requires std::copy_constructible<_View>
+  {
+    return __base_;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator begin() {
+    __current_.__emplace(ranges::begin(__base_));
+    __remainder_ = __n_;
+    return __outer_iterator(*this);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept { return std::default_sentinel; }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr auto size()
+    requires sized_range<_View>
+  {
+    return std::__to_unsigned_like(ranges::__div_ceil(ranges::distance(__base_), __n_));
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+    requires sized_range<const _View>
+  {
+    return std::__to_unsigned_like(ranges::__div_ceil(ranges::distance(__base_), __n_));
+  }
+};
+
+template <view _View>
+  requires input_range<_View>
+class chunk_view<_View>::__outer_iterator {
+  friend chunk_view;
+
+  chunk_view* __parent_;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __outer_iterator(chunk_view& __parent) : __parent_(std::addressof(__parent)) {}
+
+public:
+  class value_type;
+  using iterator_concept = input_iterator_tag;
+  using difference_type  = range_difference_t<_View>;
+
+  _LIBCPP_HIDE_FROM_ABI __outer_iterator(__outer_iterator&&) = default;
+
+  _LIBCPP_HIDE_FROM_ABI __outer_iterator& operator=(__outer_iterator&&) = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const {
+    _LIBCPP_ASSERT_PEDANTIC(*this != default_sentinel, "Trying to dereference past-the-end chunk_view iterator.");
+    return value_type(*__parent_);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator& operator++() {
+    ranges::advance(*__parent_->__current_, __parent_->__remainder_, ranges::end(__parent_->__base_));
+    __parent_->__remainder_ = __parent_->__n_;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __outer_iterator& __i, default_sentinel_t) {
+    return *__i.__parent_->__current_ == ranges::end(__i.__parent_->__base_) && __i.__parent_->__remainder_ != 0;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(default_sentinel_t, const __outer_iterator& __i)
+    requires sized_sentinel_for<sentinel_t<_View>, iterator_t<_View>>
+  {
+    const auto __dist = ranges::end(__i.__parent_->__base_) - *__i.__parent_->__current_;
+    if (__dist < __i.__parent_->__remainder_)
+      return __dist == 0 ? 0 : 1;
+    return ranges::__div_ceil(__dist - __i.__parent_->__remainder_, __i.__parent_->__n_) + 1;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __outer_iterator& __i, default_sentinel_t __s)
+    requires sized_sentinel_for<sentinel_t<_View>, iterator_t<_View>>
+  {
+    return -(__s - __i);
+  }
+};
+
+template <view _View>
+  requires input_range<_View>
+class chunk_view<_View>::__outer_iterator::value_type : public view_interface<value_type> {
+  friend __outer_iterator;
+
+  chunk_view* __parent_;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit value_type(chunk_view& __parent) : __parent_(std::addressof(__parent)) {}
+
+public:
+  _LIBCPP_HIDE_FROM_ABI constexpr __inner_iterator begin() const noexcept { return __inner_iterator(*__parent_); }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept { return default_sentinel; }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+    requires sized_sentinel_for<sentinel_t<_View>, iterator_t<_View>>
+  {
+    return std::__to_unsigned_like(
+        ranges::min(__parent_->__remainder_, ranges::end(__parent_->__base_) - *__parent_->__current_));
+  }
+};
+
+template <view _View>
+  requires input_range<_View>
+class chunk_view<_View>::__inner_iterator {
+  friend chunk_view;
+
+  chunk_view* __parent_;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __inner_iterator(chunk_view& __parent)
+      : __parent_(std::addressof(__parent)) {}
+
+public:
+  using iterator_concept = input_iterator_tag;
+  using difference_type  = range_difference_t<_View>;
+  using value_type       = range_value_t<_View>;
+
+  _LIBCPP_HIDE_FROM_ABI __inner_iterator(__inner_iterator&&) = default;
+
+  _LIBCPP_HIDE_FROM_ABI __inner_iterator& operator=(__inner_iterator&&) = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_View> base() const& { return *__parent_->__current_; }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr range_reference_t<_View> operator*() const {
+    _LIBCPP_ASSERT_PEDANTIC(*this != default_sentinel, "Trying to dereference past-the-end chunk_view iterator");
+    return **__parent_->__current_;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __inner_iterator& operator++() {
+    ++*__parent_->__current_;
+    if (*__parent_->__current_ == ranges::end(__parent_->__base_))
+      __parent_->__remainder_ = 0;
+    else
+      --__parent_->__remainder_;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __inner_iterator& __i, default_sentinel_t) {
+    return __i.__parent_->__remainder_ == 0;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(default_sentinel_t, const __inner_iterator& __i)
+    requires sized_sentinel_for<sentinel_t<_View>, iterator_t<_View>>
+  {
+    return ranges::min(__i.__parent_->__remainder_, ranges::end(__i.__parent_->__base_) - *__i.__parent_->__current_);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __inner_iterator& __i, default_sentinel_t __s)
+    requires sized_sentinel_for<sentinel_t<_View>, iterator_t<_View>>
+  {
+    return -(__s - __i);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto
+  iter_move(const __inner_iterator& __i) noexcept(noexcept(ranges::iter_move(*__i.__parent_->__current_))) {
+    return ranges::iter_move(*__i.__parent_->__current_);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr void
+  iter_swap(const __inner_iterator& __x, const __inner_iterator& __y) noexcept(
+      noexcept((ranges::iter_swap(*__x.__parent_->__current_, *__y.__parent_->__current_))))
+    requires indirectly_swappable<iterator_t<_View>>
+  {
+    return ranges::iter_swap(*__x.__parent_->__current_, *__y.__parent_->__current_);
+  }
+};
+
+template <view _View>
+  requires forward_range<_View>
+class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS chunk_view<_View> : public view_interface<chunk_view<_View>> {
+  _LIBCPP_NO_UNIQUE_ADDRESS _View __base_;
+  _LIBCPP_NO_UNIQUE_ADDRESS range_difference_t<_View> __n_;
+
+  template <bool _Const>
+  class __iterator;
+
+public:
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit chunk_view(_View __base, range_difference_t<_View> __n)
+      : __base_(std::move(__base)), __n_(__n) {
+    _LIBCPP_ASSERT_PEDANTIC(__n > 0, "Trying to construct a chunk_view with chunk size <= 0");
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
+    requires copy_constructible<_View>
+  {
+    return __base_;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
+    requires(!__simple_view<_View>)
+  {
+    return __iterator<false>(this, ranges::begin(__base_));
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
+    requires forward_range<const _View>
+  {
+    return __iterator<true>(this, ranges::begin(__base_));
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr auto end()
+    requires(!__simple_view<_View>)
+  {
+    if constexpr (common_range<_View> && sized_range<_View>) {
+      auto __missing = (__n_ - ranges::distance(__base_) % __n_) % __n_;
+      return __iterator<false>(this, ranges::end(__base_), __missing);
+    } else if constexpr (common_range<_View> && !bidirectional_range<_View>)
+      return __iterator<false>(this, ranges::end(__base_));
+    else
+      return default_sentinel;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
+    requires forward_range<const _View>
+  {
+    if constexpr (common_range<const _View> && sized_range<const _View>) {
+      auto __missing = (__n_ - ranges::distance(__base_) % __n_) % __n_;
+      return __iterator<true>(this, ranges::end(__base_), __missing);
+    } else if constexpr (common_range<const _View> && !bidirectional_range<const _View>)
+      return __iterator<true>(this, ranges::end(__base_));
+    else
+      return default_sentinel;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr auto size()
+    requires sized_range<_View>
+  {
+    return std::__to_unsigned_like(ranges::__div_ceil(ranges::distance(__base_), __n_));
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+    requires sized_range<const _View>
+  {
+    return std::__to_unsigned_like(ranges::__div_ceil(ranges::distance(__base_), __n_));
+  }
+};
+
+template <view _View>
+  requires forward_range<_View>
+template <bool _Const>
+class chunk_view<_View>::__iterator {
+  friend chunk_view;
+
+  using _Parent _LIBCPP_NODEBUG = __maybe_const<_Const, chunk_view>;
+  using _Base   _LIBCPP_NODEBUG = __maybe_const<_Const, _View>;
+
+  iterator_t<_Base> __current_         = iterator_t<_Base>();
+  sentinel_t<_Base> __end_             = sentinel_t<_Base>();
+  range_difference_t<_Base> __n_       = 0;
+  range_difference_t<_Base> __missing_ = 0;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator(
+      _Parent* __parent, iterator_t<_Base> __current, range_difference_t<_Base> __missing = 0)
+      : __current_(__current), __end_(ranges::end(__parent->__base_)), __n_(__parent->__n_), __missing_(__missing) {}
+
+  static consteval auto __get_iterator_concept() {
+    if constexpr (random_access_range<_Base>)
+      return random_access_iterator_tag{};
+    else if constexpr (bidirectional_range<_Base>)
+      return bidirectional_iterator_tag{};
+    else
+      return forward_iterator_tag{};
+  }
+
+public:
+  using iterator_category = input_iterator_tag;
+  using iterator_concept  = decltype(__iterator::__get_iterator_concept());
+  using value_type        = decltype(views::take(subrange(__current_, __end_), __n_));
+  using difference_type   = range_difference_t<_Base>;
+
+  _LIBCPP_HIDE_FROM_ABI __iterator() = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i)
+    requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> &&
+                 convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
+      : __current_(std::move(__i.__current_)),
+        __end_(std::move(__i.__end_)),
+        __n_(__i.__n_),
+        __missing_(__i.__missing_) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() const { return __current_; }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const {
+    _LIBCPP_ASSERT_PEDANTIC(__current_ != __end_, "Trying to dereference past-the-end chunk_view iterator");
+    return views::take(subrange(__current_, __end_), __n_);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr value_type operator[](difference_type __pos) const
+    requires random_access_range<_Base>
+  {
+    return *(*this + __pos);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
+    _LIBCPP_ASSERT_PEDANTIC(__current_ != __end_, "Trying to advance past-the-end chunk_view iterator");
+    __missing_ = ranges::advance(__current_, __n_, __end_);
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) {
+    auto __tmp = *this;
+    ++*this;
+    return __tmp;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--()
+    requires bidirectional_range<_Base>
+  {
+    ranges::advance(__current_, __missing_ - __n_);
+    __missing_ = 0;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) {
+    auto __tmp = *this;
+    --*this;
+    return __tmp;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __x)
+    requires random_access_range<_Base>
+  {
+    if (__x > 0) {
+      _LIBCPP_ASSERT_PEDANTIC(ranges::distance(__current_, __end_) > __n_ * (__x - 1),
+                              "Trying to advance chunk_view iterator out of range");
+      ranges::advance(__current_, __n_ * (__x - 1));
+      __missing_ = ranges::advance(__current_, __n_, __end_);
+    } else if (__x < 0) {
+      ranges::advance(__current_, __n_ * __x + __missing_);
+      __missing_ = 0;
+    }
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __x)
+    requires random_access_range<_Base>
+  {
+    return *this += -__x;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) {
+    r...
[truncated]

@github-actions
Copy link

github-actions bot commented Dec 9, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

This PR implements libc++ `std::ranges::chunk_view` in header
<__ranges/chunk_view.h>.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants