[libcxx] [llvm] [libc++] Implement P2442R1 `std::views::chunk` (PR #171234)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 8 20:54:37 PST 2025
https://github.com/anonymouspc updated https://github.com/llvm/llvm-project/pull/171234
>From 25afd3bbf2b053e5ee99195ba7b4c0268cced6c0 Mon Sep 17 00:00:00 2001
From: anonymouspc <shyeyian at petalmail.com>
Date: Mon, 8 Dec 2025 17:55:02 +0800
Subject: [PATCH 01/11] [libc++] Implement P2242R1 `std::views::chunk`
This PR implements libc++ `std::ranges::chunk_view` in header
<__ranges/chunk_view.h>.
---
libcxx/docs/FeatureTestMacroTable.rst | 2 +-
libcxx/docs/ReleaseNotes/22.rst | 1 +
libcxx/docs/Status/Cxx23Papers.csv | 2 +-
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__cxx03/module.modulemap | 1 +
libcxx/include/__ranges/chunk_view.h | 544 ++++++++++++++++++
libcxx/include/module.modulemap.in | 4 +
libcxx/include/ranges | 12 +
libcxx/include/version | 2 +-
libcxx/modules/std/ranges.inc | 6 +-
.../ranges.version.compile.pass.cpp | 32 +-
.../version.version.compile.pass.cpp | 32 +-
.../range.chunk/adaptor.pass.cpp | 73 +++
.../range.adaptors/range.chunk/base.pass.cpp | 41 ++
.../range.adaptors/range.chunk/begin.pass.cpp | 63 ++
.../range.chunk/ctad.compile.pass.cpp | 48 ++
.../range.adaptors/range.chunk/end.pass.cpp | 64 +++
.../range.chunk/general.pass.cpp | 47 ++
.../range.chunk.iter/compare.pass.cpp | 44 ++
.../range.chunk.iter/decrement.pass.cpp | 48 ++
.../range.chunk.iter/increment.pass.cpp | 46 ++
.../ranges/range.adaptors/range.chunk/types.h | 70 +++
.../generate_feature_test_macro_components.py | 1 -
.../gn/secondary/libcxx/include/BUILD.gn | 1 +
24 files changed, 1135 insertions(+), 50 deletions(-)
create mode 100644 libcxx/include/__ranges/chunk_view.h
create mode 100644 libcxx/test/std/ranges/range.adaptors/range.chunk/adaptor.pass.cpp
create mode 100644 libcxx/test/std/ranges/range.adaptors/range.chunk/base.pass.cpp
create mode 100644 libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
create mode 100644 libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp
create mode 100644 libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp
create mode 100644 libcxx/test/std/ranges/range.adaptors/range.chunk/general.pass.cpp
create mode 100644 libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/compare.pass.cpp
create mode 100644 libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/decrement.pass.cpp
create mode 100644 libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/increment.pass.cpp
create mode 100644 libcxx/test/std/ranges/range.adaptors/range.chunk/types.h
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..151bd6233ba60 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/PR171234>`__)
Improvements and New Features
-----------------------------
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index b655384bad7f2..7aa2f07d9bb57 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -48,7 +48,7 @@
"`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>`__",""
+"`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>`__","Only ``views::chunk`` is implemented."
"`P2443R1 <https://wg21.link/P2443R1>`__","``views::chunk_by``","2022-02 (Virtual)","|Complete|","18","`#105188 <https://github.com/llvm/llvm-project/issues/105188>`__",""
"","","","","","",""
"`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>`__",""
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..ae37c9784e081
--- /dev/null
+++ b/libcxx/include/__ranges/chunk_view.h
@@ -0,0 +1,544 @@
+// -*- 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) {
+ return __x.__current_ == __y.__current_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, default_sentinel_t) {
+ return __x.__current_ == __x.__end_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
+ requires random_access_range<_Base>
+ {
+ return __x.__current_ < __y.__current_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
+ requires random_access_range<_Base>
+ {
+ return __y < __x;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
+ requires random_access_range<_Base>
+ {
+ return !(__y < __x);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
+ requires random_access_range<_Base>
+ {
+ return !(__x < __y);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
+ requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>>
+ {
+ return __x.__current_ <=> __y.__current_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __i, difference_type __pos)
+ requires random_access_range<_Base>
+ {
+ auto __r = __i;
+ __r += __pos;
+ return __r;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __pos, const __iterator& __i)
+ requires random_access_range<_Base>
+ {
+ auto __r = __i;
+ __r += __pos;
+ return __r;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __i, difference_type __pos)
+ requires random_access_range<_Base>
+ {
+ auto __r = __i;
+ __r -= __pos;
+ return __r;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __i, const __iterator& __j)
+ requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>
+ {
+ return (__i.__current_ - __j.__current_ + __i.__missing_ - __j.__missing_) / __i.__n_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(default_sentinel_t, const __iterator& __i)
+ requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
+ {
+ return ranges::__div_ceil(__i.__end_ - __i.__current_, __i.__n_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __i, default_sentinel_t __s)
+ requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
+ {
+ return -(__s - __i);
+ }
+};
+
+template <class _Range>
+chunk_view(_Range&&, range_difference_t<_Range>) -> chunk_view<views::all_t<_Range>>;
+
+template <class _View>
+inline constexpr bool enable_borrowed_range<chunk_view<_View>> = forward_range<_View> && enable_borrowed_range<_View>;
+
+namespace views {
+namespace __chunk {
+struct __fn {
+ template <viewable_range _Range>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, range_difference_t<_Range> __n) const
+ noexcept(noexcept(/**/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n))))
+ -> decltype(/*--*/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n))) {
+ return /*-------------*/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n));
+ }
+
+ template <class _DifferenceType>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_DifferenceType __n) const
+ noexcept(is_nothrow_constructible_v<decay_t<_DifferenceType>, _DifferenceType>) {
+ return __pipeable(std::__bind_back(*this, std::forward<_DifferenceType>(__n)));
+ }
+};
+
+} // namespace __chunk
+
+inline namespace __cpo {
+inline constexpr auto chunk = __chunk::__fn{};
+} // namespace __cpo
+} // namespace views
+
+} // namespace ranges
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_CHUNK_VIEW_H
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 955a7cc3e364a..8d4123a1e6bb2 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1855,6 +1855,10 @@ module std [system] {
header "__ranges/chunk_by_view.h"
export std.functional.bind_back
}
+ module chunk_view {
+ header "__ranges/chunk_view.h"
+ export std.functional.bind_back
+ }
module common_view { header "__ranges/common_view.h" }
module concepts { header "__ranges/concepts.h" }
module container_compatible_range { header "__ranges/container_compatible_range.h" }
diff --git a/libcxx/include/ranges b/libcxx/include/ranges
index cfaa66a0831b3..8fb65f5f4cad2 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -367,6 +367,17 @@ namespace std::ranges {
class chunk_by_view; // C++23
namespace views { inline constexpr unspecified chunk_by = unspecified; } // C++23
+
+ // [range.chunk]
+ template <view V>
+ requires input_range<V>
+ class chunk_view; // C++23
+
+ template <view V>
+ requires forward_range<V>
+ class chunk_view<V>; // C++23
+
+ namespace views { inline constexpr unspecified chunk = unspecified; } // C++23
}
namespace std {
@@ -450,6 +461,7 @@ namespace std {
# if _LIBCPP_STD_VER >= 23
# include <__ranges/as_rvalue_view.h>
# include <__ranges/chunk_by_view.h>
+# include <__ranges/chunk_view.h>
# include <__ranges/from_range.h>
# include <__ranges/join_with_view.h>
# include <__ranges/repeat_view.h>
diff --git a/libcxx/include/version b/libcxx/include/version
index 05532ea731ff3..daeb88aa2a79d 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -522,7 +522,7 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_ranges 202406L
// # define __cpp_lib_ranges_as_const 202207L
# define __cpp_lib_ranges_as_rvalue 202207L
-// # define __cpp_lib_ranges_chunk 202202L
+# define __cpp_lib_ranges_chunk 202202L
# define __cpp_lib_ranges_chunk_by 202202L
# define __cpp_lib_ranges_contains 202207L
# define __cpp_lib_ranges_find_last 202207L
diff --git a/libcxx/modules/std/ranges.inc b/libcxx/modules/std/ranges.inc
index cc7daa3cd1aec..8f571eaec2536 100644
--- a/libcxx/modules/std/ranges.inc
+++ b/libcxx/modules/std/ranges.inc
@@ -315,15 +315,17 @@ export namespace std {
using std::ranges::views::adjacent_transform;
using std::ranges::views::pairwise_transform;
} // namespace views
+#endif
+#if _LIBCPP_STD_VER >= 23
using std::ranges::chunk_view;
- using std::ranges::chunk_view<V>;
-
namespace views {
using std::ranges::views::chunk;
}
+#endif
+#if 0
using std::ranges::slide_view;
namespace views {
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
index 5116864879485..41e1603f62350 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
@@ -270,17 +270,11 @@
# error "__cpp_lib_ranges_as_rvalue should have the value 202207L in c++23"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_ranges_chunk
-# error "__cpp_lib_ranges_chunk should be defined in c++23"
-# endif
-# if __cpp_lib_ranges_chunk != 202202L
-# error "__cpp_lib_ranges_chunk should have the value 202202L in c++23"
-# endif
-# else
-# ifdef __cpp_lib_ranges_chunk
-# error "__cpp_lib_ranges_chunk should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_ranges_chunk
+# error "__cpp_lib_ranges_chunk should be defined in c++23"
+# endif
+# if __cpp_lib_ranges_chunk != 202202L
+# error "__cpp_lib_ranges_chunk should have the value 202202L in c++23"
# endif
# ifndef __cpp_lib_ranges_chunk_by
@@ -387,17 +381,11 @@
# error "__cpp_lib_ranges_as_rvalue should have the value 202207L in c++26"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_ranges_chunk
-# error "__cpp_lib_ranges_chunk should be defined in c++26"
-# endif
-# if __cpp_lib_ranges_chunk != 202202L
-# error "__cpp_lib_ranges_chunk should have the value 202202L in c++26"
-# endif
-# else
-# ifdef __cpp_lib_ranges_chunk
-# error "__cpp_lib_ranges_chunk should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_ranges_chunk
+# error "__cpp_lib_ranges_chunk should be defined in c++26"
+# endif
+# if __cpp_lib_ranges_chunk != 202202L
+# error "__cpp_lib_ranges_chunk should have the value 202202L in c++26"
# endif
# ifndef __cpp_lib_ranges_chunk_by
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 996ec29dce697..a825934e49b3a 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -5700,17 +5700,11 @@
# error "__cpp_lib_ranges_as_rvalue should have the value 202207L in c++23"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_ranges_chunk
-# error "__cpp_lib_ranges_chunk should be defined in c++23"
-# endif
-# if __cpp_lib_ranges_chunk != 202202L
-# error "__cpp_lib_ranges_chunk should have the value 202202L in c++23"
-# endif
-# else
-# ifdef __cpp_lib_ranges_chunk
-# error "__cpp_lib_ranges_chunk should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_ranges_chunk
+# error "__cpp_lib_ranges_chunk should be defined in c++23"
+# endif
+# if __cpp_lib_ranges_chunk != 202202L
+# error "__cpp_lib_ranges_chunk should have the value 202202L in c++23"
# endif
# ifndef __cpp_lib_ranges_chunk_by
@@ -7619,17 +7613,11 @@
# error "__cpp_lib_ranges_as_rvalue should have the value 202207L in c++26"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_ranges_chunk
-# error "__cpp_lib_ranges_chunk should be defined in c++26"
-# endif
-# if __cpp_lib_ranges_chunk != 202202L
-# error "__cpp_lib_ranges_chunk should have the value 202202L in c++26"
-# endif
-# else
-# ifdef __cpp_lib_ranges_chunk
-# error "__cpp_lib_ranges_chunk should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_ranges_chunk
+# error "__cpp_lib_ranges_chunk should be defined in c++26"
+# endif
+# if __cpp_lib_ranges_chunk != 202202L
+# error "__cpp_lib_ranges_chunk should have the value 202202L in c++26"
# endif
# ifndef __cpp_lib_ranges_chunk_by
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/adaptor.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/adaptor.pass.cpp
new file mode 100644
index 0000000000000..8993c54ea4565
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/adaptor.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// std::views::chunk
+
+#include <ranges>
+
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <concepts>
+#include <span>
+
+#include "test_range.h"
+#include "types.h"
+
+constexpr bool test() {
+ std::array array = {1, 1, 1, 2, 2, 2, 3, 3};
+ std::span<int> span = {array.data(), 8};
+
+ // Test `views::chunk(view, n)`
+ {
+ auto chunked = std::views::chunk(span, 2);
+ static_assert(std::same_as<decltype(chunked), std::ranges::chunk_view<std::span<int>>>);
+ assert(std::ranges::equal(*chunked.begin(), std::array{1, 1}));
+ }
+
+ // Test `views::chunk(input_view, n)`
+ {
+ auto input = exactly_input_view<decltype(span)>(span);
+ auto chunked = std::views::chunk(input, 3);
+ assert(std::ranges::equal(*chunked.begin(), std::array{1, 1, 1}));
+ }
+
+ // Test `views::chunk(n)(range)`
+ {
+ auto adaptor = std::views::chunk(4);
+ auto chunked = adaptor(span);
+ static_assert(std::same_as<decltype(chunked), std::ranges::chunk_view<std::span<int>>>);
+ assert(std::ranges::equal(*chunked.begin(), std::array{1, 1, 1, 2}));
+ }
+
+ // Test `view | views::chunk`
+ {
+ auto chunked = span | std::views::chunk(5);
+ static_assert(std::same_as<decltype(chunked), std::ranges::chunk_view<std::span<int>>>);
+ static_assert(std::ranges::random_access_range<decltype(chunked)>);
+ assert(std::ranges::equal(*chunked.begin(), std::array{1, 1, 1, 2, 2}));
+ }
+
+ // Test `views::chunk | adaptor`
+ {
+ auto multi_adaptor = std::views::chunk(1) | std::views::join;
+ auto rejoined = span | multi_adaptor;
+ assert(std::ranges::equal(rejoined, span));
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/base.pass.cpp
new file mode 100644
index 0000000000000..798349a7784d8
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/base.pass.cpp
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// std::views::chunk
+
+#include <ranges>
+
+#include <array>
+#include <cassert>
+#include <span>
+
+#include "test_range.h"
+
+constexpr bool test() {
+ std::array array = {1, 1, 1, 2, 2, 2, 3, 3};
+
+ // Test `chunk_view.base()`
+ {
+ auto view = array | std::views::chunk(3);
+ auto base = view.begin().base();
+ assert(base == array.begin());
+ base = view.end().base();
+ assert(base == array.end());
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
new file mode 100644
index 0000000000000..eb4818b838725
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// std::views::chunk
+
+#include <ranges>
+
+#include <algorithm>
+#include <cassert>
+#include <list>
+
+#include "test_range.h"
+
+constexpr bool test() {
+ std::list<int> full_list = {1, 1, 1, 2, 2, 2, 3, 3};
+ std::list<int> empty_list = {};
+
+ // Test `chunk_view.begin()`
+ {
+ auto view = full_list | std::views::chunk(3);
+ auto it = view.begin();
+ assert(std::ranges::equal(*it, std::list{1, 1, 1}));
+ assert(std::ranges::equal(*++it, std::list{2, 2, 2}));
+ assert(std::ranges::equal(*++it, std::list{3, 3})); // The last chunk has only 2 elements.
+ assert(++it == view.end()); // Reaches end.
+
+ view = full_list | std::views::chunk(5);
+ it = view.begin();
+ assert(std::ranges::equal(*it, std::list{1, 1, 1, 2, 2}));
+ assert(std::ranges::equal(*++it, std::list{2, 3, 3}));
+ }
+
+ // Test `empty_chunk_view.begin()`
+ {
+ auto view = empty_list | std::views::chunk(3);
+ assert(view.size() == 0);
+ assert(view.begin() == view.end());
+ }
+
+ // Test `small_view_with_big_chunk.begin()`
+ {
+ auto view = full_list | std::views::chunk(314159);
+ assert(view.size() == 1);
+ assert(std::ranges::equal(*view.begin(), full_list));
+ assert(++view.begin() == view.end());
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp
new file mode 100644
index 0000000000000..55fe4ca976976
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// std::views::chunk
+
+#include <ranges>
+
+struct view : std::ranges::view_base {
+ int* begin() const;
+ int* end() const;
+};
+
+struct range {
+ int* begin() const;
+ int* end() const;
+};
+
+struct borrowed_range {
+ int* begin() const;
+ int* end() const;
+};
+
+template <>
+inline constexpr bool std::ranges::enable_borrowed_range<borrowed_range> = true;
+
+void testCTAD() {
+ view v;
+ range r;
+ borrowed_range br;
+
+ static_assert(std::same_as< decltype(std::ranges::chunk_view(v, 0)), std::ranges::chunk_view<view> >);
+ static_assert(std::same_as< decltype(std::ranges::chunk_view(std::move(v), 0)), std::ranges::chunk_view<view> >);
+ static_assert(
+ std::same_as< decltype(std::ranges::chunk_view(r, 0)), std::ranges::chunk_view<std::ranges::ref_view<range>> >);
+ static_assert(std::same_as< decltype(std::ranges::chunk_view(std::move(r), 0)),
+ std::ranges::chunk_view<std::ranges::owning_view<range>> >);
+ static_assert(std::same_as< decltype(std::ranges::chunk_view(br, 0)),
+ std::ranges::chunk_view<std::ranges::ref_view<borrowed_range>> >);
+ static_assert(std::same_as< decltype(std::ranges::chunk_view(std::move(br), 0)),
+ std::ranges::chunk_view<std::ranges::owning_view<borrowed_range>> >);
+}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp
new file mode 100644
index 0000000000000..056e7bb57fa5b
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// std::views::chunk
+
+#include <ranges>
+
+#include <algorithm>
+#include <cassert>
+#include <concepts>
+#include <forward_list>
+#include <list>
+
+#include "test_range.h"
+#include "types.h"
+
+constexpr bool test() {
+ std::list list = {1, 1, 1, 2, 2, 2, 3, 3};
+ std::forward_list forward_list = {1, 1, 1, 2, 2, 2, 3, 3};
+
+ // Test `chunk_view.end()`
+ {
+ auto view = list | std::views::chunk(3);
+ auto it = view.end();
+ assert(std::ranges::equal(*--it, std::list{3, 3})); // We can adjust the tailing chunk-size.
+ assert(std::ranges::equal(*--it, std::list{2, 2, 2}));
+ assert(std::ranges::equal(*--it, std::list{1, 1, 1}));
+ }
+
+ // Test `not_sized_chunk_view.end()`
+ {
+ auto not_sized_list = not_sized_view(list | std::views::all);
+ auto view = not_sized_list | std::views::chunk(4);
+ static_assert(std::ranges::bidirectional_range<decltype(view)>);
+ static_assert(!std::ranges::sized_range<decltype(view)>);
+ static_assert(
+ std::same_as<
+ decltype(view.end()),
+ std::
+ default_sentinel_t>); // We cannot handle the tailing chunk without size info, so we forbids one to derement from end().
+ }
+
+ // Test `forward_chunk_view.end()`
+ {
+ auto view = list | std::views::chunk(5);
+ assert(++(++view.begin()) == view.end());
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/general.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/general.pass.cpp
new file mode 100644
index 0000000000000..cdfb3edee38cb
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/general.pass.cpp
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// std::views::chunk
+
+#include <ranges>
+
+#include <algorithm>
+#include <cassert>
+#include <string_view>
+
+#include "test_range.h"
+
+constexpr bool test() {
+ auto str = std::string_view("Cheese the chicken chunk by chunk on truck by truck");
+ // clang-format off
+ auto str2 = str
+ | std::views::chunk(4)
+ | std::views::join
+ | std::views::chunk(314159)
+ | std::views::take(1)
+ | std::views::join
+ | std::views::lazy_split(' ')
+ | std::views::chunk(2)
+ | std::views::transform([] (auto&& subview)
+ {
+ return subview | std::views::join_with(' ');
+ })
+ | std::views::join_with(' ');
+ // clang-format on
+ assert(std::ranges::equal(str, str2));
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/compare.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/compare.pass.cpp
new file mode 100644
index 0000000000000..ade621351a6cb
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/compare.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// std::views::chunk
+
+#include <ranges>
+
+#include <algorithm>
+#include <cassert>
+#include <vector>
+
+#include "test_range.h"
+
+constexpr bool test() {
+ std::vector<int> vector = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+
+ // Test `chunk_view.__iterator.operator<=>`
+ {
+ auto view = vector | std::views::chunk(5);
+ assert(view.begin() < view.end());
+ assert(++view.begin() < view.end());
+ assert(view.begin() + 3 == view.end());
+ assert(view.begin() + 3 > view.end() - 1);
+ assert((view.begin() <=> view.end()) == std::strong_ordering::less);
+ assert((view.begin() + 1 <=> view.end() - 2) == std::strong_ordering::equal);
+ assert((view.end() <=> view.begin()) == std::strong_ordering::greater);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/decrement.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/decrement.pass.cpp
new file mode 100644
index 0000000000000..32ad809eda1b8
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/decrement.pass.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// std::views::chunk
+
+#include <ranges>
+
+#include <algorithm>
+#include <cassert>
+#include <vector>
+
+#include "test_range.h"
+
+constexpr bool test() {
+ std::vector<int> vector = {1, 2, 3, 4, 5, 6, 7, 8};
+
+ // Test `chunk_view.__iterator.operator--`
+ {
+ auto view = vector | std::views::chunk(2);
+ assert(std::ranges::equal(*(--view.end()), std::vector{7, 8}));
+ }
+
+ // Test `chunk_view.__iterator.operator-`
+ {
+ auto view = vector | std::views::chunk(3);
+ assert(view.end() - 3 == view.begin());
+ assert((view.end() -= 3) == view.begin());
+ assert(view.size() == 3);
+ assert(view.end() - view.begin() == 3);
+ assert(std::ranges::equal(*(view.end() - 2), std::vector{4, 5, 6}));
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/increment.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/increment.pass.cpp
new file mode 100644
index 0000000000000..2e12b90344ea2
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/increment.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// std::views::chunk
+
+#include <ranges>
+
+#include <algorithm>
+#include <cassert>
+#include <vector>
+
+#include "test_range.h"
+
+constexpr bool test() {
+ std::vector<int> vector = {1, 2, 3, 4, 5, 6, 7, 8};
+
+ // Test `chunk_view.__iterator.operator++`
+ {
+ auto view = vector | std::views::chunk(2);
+ assert(std::ranges::equal(*(++view.begin()), std::vector{3, 4}));
+ }
+
+ // Test `chunk_view.__iterator.operator+`
+ {
+ auto view = vector | std::views::chunk(3);
+ assert(view.begin() + 3 == view.end());
+ assert((view.begin() += 3) == view.end());
+ assert(std::ranges::equal(*(view.begin() + 2), std::vector{7, 8}));
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
\ No newline at end of file
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/types.h b/libcxx/test/std/ranges/range.adaptors/range.chunk/types.h
new file mode 100644
index 0000000000000..09942d4212ef1
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/types.h
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_CHUNK_TYPES_H
+#define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_CHUNK_TYPES_H
+
+#include <forward_list>
+#include <ranges>
+#include <vector>
+
+template <std::ranges::view View>
+struct exactly_input_view : View, std::ranges::view_interface<exactly_input_view<View>> {
+ struct iterator : std::ranges::iterator_t<View> {
+ using iterator_concept = std::input_iterator_tag;
+ constexpr iterator() = default;
+ constexpr iterator(std::ranges::iterator_t<View> i) : std::ranges::iterator_t<View>(i) {}
+ constexpr auto operator*() const { return std::ranges::iterator_t<View>::operator*(); }
+ friend constexpr void operator+(iterator, int) = delete;
+ friend constexpr void operator+(int, iterator) = delete;
+ friend constexpr void operator-(iterator, int) = delete;
+ friend constexpr void operator-(iterator, iterator) = delete;
+ friend constexpr iterator& operator++(iterator& self) {
+ self.std::ranges::template iterator_t<View>::operator++();
+ return self;
+ }
+ friend constexpr void operator++(iterator& self, int) { ++self; }
+ friend constexpr void operator--(iterator&) = delete;
+ friend constexpr void operator--(iterator&, int) = delete;
+ };
+
+ constexpr iterator begin(this auto&& self) { return iterator(self.View::begin()); }
+ constexpr iterator end(this auto&& self) { return iterator(self.View::end()); }
+};
+
+template <std::ranges::view View>
+struct not_sized_view : View, std::ranges::view_interface<not_sized_view<View>> {
+ struct iterator : std::ranges::iterator_t<View> {
+ using iterator_concept = std::bidirectional_iterator_tag;
+ constexpr iterator() = default;
+ constexpr iterator(std::ranges::iterator_t<View> i) : std::ranges::iterator_t<View>(i) {}
+ friend constexpr void operator-(iterator, iterator) = delete;
+ friend constexpr iterator& operator++(iterator& self) {
+ self.std::ranges::template iterator_t<View>::operator++();
+ return self;
+ }
+ friend constexpr iterator operator++(iterator& self, int) { return ++self; }
+ friend constexpr iterator& operator--(iterator& self) {
+ self.std::ranges::template iterator_t<View>::operator--();
+ return self;
+ }
+ friend constexpr iterator operator--(iterator& self, int) { return --self; }
+ };
+
+ constexpr iterator begin(this auto&& self) { return iterator(self.View::begin()); }
+ constexpr iterator end(this auto&& self) { return iterator(self.View::end()); }
+ constexpr auto size() const = delete;
+};
+
+template <std::ranges::view View>
+not_sized_view(View) -> not_sized_view<View>;
+
+template <std::ranges::view View>
+inline constexpr bool std::ranges::disable_sized_range<not_sized_view<View>> = true;
+
+#endif
\ No newline at end of file
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 0802f865f9406..8cec6fe9b971b 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1103,7 +1103,6 @@ def add_version_header(tc):
"name": "__cpp_lib_ranges_chunk",
"values": {"c++23": 202202},
"headers": ["ranges"],
- "unimplemented": True,
},
{
"name": "__cpp_lib_ranges_chunk_by",
diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
index 9755fe3a7ea50..16be8fa8de795 100644
--- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
+++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
@@ -1352,6 +1352,7 @@ if (current_toolchain == default_toolchain) {
"__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",
>From f5f374fbd3b24c3749f98f960dd58ee9881dcdcb Mon Sep 17 00:00:00 2001
From: anonymouspc <shyeyian at petalmail.com>
Date: Tue, 9 Dec 2025 11:03:07 +0800
Subject: [PATCH 02/11] post-code-review
---
libcxx/include/__cxx03/module.modulemap | 1 -
libcxx/include/__ranges/chunk_view.h | 8 ++++----
.../ranges/range.adaptors/range.chunk/adaptor.pass.cpp | 4 ++--
.../std/ranges/range.adaptors/range.chunk/base.pass.cpp | 4 ++--
.../std/ranges/range.adaptors/range.chunk/begin.pass.cpp | 4 ++--
.../range.adaptors/range.chunk/ctad.compile.pass.cpp | 2 +-
.../std/ranges/range.adaptors/range.chunk/end.pass.cpp | 4 ++--
.../ranges/range.adaptors/range.chunk/general.pass.cpp | 4 ++--
.../range.chunk/range.chunk.iter/compare.pass.cpp | 4 ++--
.../range.chunk/range.chunk.iter/decrement.pass.cpp | 4 ++--
.../range.chunk/range.chunk.iter/increment.pass.cpp | 4 ++--
libcxx/test/std/ranges/range.adaptors/range.chunk/types.h | 2 +-
12 files changed, 22 insertions(+), 23 deletions(-)
diff --git a/libcxx/include/__cxx03/module.modulemap b/libcxx/include/__cxx03/module.modulemap
index b7eee575090ce..34a2d0f25fc45 100644
--- a/libcxx/include/__cxx03/module.modulemap
+++ b/libcxx/include/__cxx03/module.modulemap
@@ -1701,7 +1701,6 @@ 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
index ae37c9784e081..25fc018ba63f9 100644
--- a/libcxx/include/__ranges/chunk_view.h
+++ b/libcxx/include/__ranges/chunk_view.h
@@ -53,7 +53,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
template <class _Integral>
-inline _LIBCPP_HIDE_FROM_ABI constexpr auto __div_ceil(_Integral __num, _Integral __denom) {
+_LIBCPP_HIDE_FROM_ABI constexpr auto __div_ceil(_Integral __num, _Integral __denom) {
_Integral __r = __num / __denom;
if (__num % __denom)
++__r;
@@ -62,7 +62,7 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr auto __div_ceil(_Integral __num, _Integra
template <view _View>
requires input_range<_View>
-class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS chunk_view : public view_interface<chunk_view<_View>> {
+class 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_;
@@ -249,7 +249,7 @@ class chunk_view<_View>::__inner_iterator {
template <view _View>
requires forward_range<_View>
-class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS chunk_view<_View> : public view_interface<chunk_view<_View>> {
+class chunk_view<_View> : public view_interface<chunk_view<_View>> {
_LIBCPP_NO_UNIQUE_ADDRESS _View __base_;
_LIBCPP_NO_UNIQUE_ADDRESS range_difference_t<_View> __n_;
@@ -513,7 +513,7 @@ namespace views {
namespace __chunk {
struct __fn {
template <viewable_range _Range>
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, range_difference_t<_Range> __n) const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&& __range, range_difference_t<_Range> __n)
noexcept(noexcept(/**/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n))))
-> decltype(/*--*/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n))) {
return /*-------------*/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n));
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/adaptor.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/adaptor.pass.cpp
index 8993c54ea4565..d37d2a25c5298 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/adaptor.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/adaptor.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++23
// std::views::chunk
@@ -70,4 +70,4 @@ int main(int, char**) {
static_assert(test());
return 0;
-}
\ No newline at end of file
+}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/base.pass.cpp
index 798349a7784d8..0cca883399e7f 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/base.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++23
// std::views::chunk
@@ -38,4 +38,4 @@ int main(int, char**) {
static_assert(test());
return 0;
-}
\ No newline at end of file
+}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
index eb4818b838725..5a55d1e343139 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++23
// std::views::chunk
@@ -60,4 +60,4 @@ int main(int, char**) {
static_assert(test());
return 0;
-}
\ No newline at end of file
+}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp
index 55fe4ca976976..ed04cd57555ff 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++23
// std::views::chunk
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp
index 056e7bb57fa5b..ccd136ab193a0 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++23
// std::views::chunk
@@ -61,4 +61,4 @@ int main(int, char**) {
static_assert(test());
return 0;
-}
\ No newline at end of file
+}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/general.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/general.pass.cpp
index cdfb3edee38cb..b9e81314a9580 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/general.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/general.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++23
// std::views::chunk
@@ -44,4 +44,4 @@ int main(int, char**) {
static_assert(test());
return 0;
-}
\ No newline at end of file
+}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/compare.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/compare.pass.cpp
index ade621351a6cb..0d335914b71c2 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/compare.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/compare.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++23
// std::views::chunk
@@ -41,4 +41,4 @@ int main(int, char**) {
static_assert(test());
return 0;
-}
\ No newline at end of file
+}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/decrement.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/decrement.pass.cpp
index 32ad809eda1b8..7bf2026c1f95d 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/decrement.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/decrement.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++23
// std::views::chunk
@@ -45,4 +45,4 @@ int main(int, char**) {
static_assert(test());
return 0;
-}
\ No newline at end of file
+}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/increment.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/increment.pass.cpp
index 2e12b90344ea2..fee4b0d2dda04 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/increment.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/range.chunk.iter/increment.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// REQUIRES: std-at-least-c++23
// std::views::chunk
@@ -43,4 +43,4 @@ int main(int, char**) {
static_assert(test());
return 0;
-}
\ No newline at end of file
+}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/types.h b/libcxx/test/std/ranges/range.adaptors/range.chunk/types.h
index 09942d4212ef1..78d41a8ec3665 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/types.h
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/types.h
@@ -67,4 +67,4 @@ not_sized_view(View) -> not_sized_view<View>;
template <std::ranges::view View>
inline constexpr bool std::ranges::disable_sized_range<not_sized_view<View>> = true;
-#endif
\ No newline at end of file
+#endif
>From b97b20c03b2f41538f34d804d4db38779e665058 Mon Sep 17 00:00:00 2001
From: anonymouspc <shyeyian at petalmail.com>
Date: Tue, 9 Dec 2025 11:03:30 +0800
Subject: [PATCH 03/11] clang-format
---
libcxx/include/__ranges/chunk_view.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/__ranges/chunk_view.h b/libcxx/include/__ranges/chunk_view.h
index 25fc018ba63f9..fd9733ecffcb6 100644
--- a/libcxx/include/__ranges/chunk_view.h
+++ b/libcxx/include/__ranges/chunk_view.h
@@ -513,9 +513,10 @@ namespace views {
namespace __chunk {
struct __fn {
template <viewable_range _Range>
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&& __range, range_difference_t<_Range> __n)
- noexcept(noexcept(/**/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n))))
- -> decltype(/*--*/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n))) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto
+ operator()(_Range&& __range, range_difference_t<_Range> __n) noexcept(
+ noexcept(/**/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n))))
+ -> decltype(/*--*/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n))) {
return /*-------------*/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n));
}
>From 1b4367d2d1cb4ce534cbd500c008d5be83615e7d Mon Sep 17 00:00:00 2001
From: anonymouspc <shyeyian at petalmail.com>
Date: Tue, 9 Dec 2025 11:59:57 +0800
Subject: [PATCH 04/11] add nodiscard attributes
---
libcxx/include/__ranges/chunk_view.h | 107 ++++++++++--------
.../ranges/range.adaptors/range.chunk/types.h | 1 -
2 files changed, 61 insertions(+), 47 deletions(-)
diff --git a/libcxx/include/__ranges/chunk_view.h b/libcxx/include/__ranges/chunk_view.h
index fd9733ecffcb6..e0495b7e9f7ab 100644
--- a/libcxx/include/__ranges/chunk_view.h
+++ b/libcxx/include/__ranges/chunk_view.h
@@ -53,7 +53,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
template <class _Integral>
-_LIBCPP_HIDE_FROM_ABI constexpr auto __div_ceil(_Integral __num, _Integral __denom) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto __div_ceil(_Integral __num, _Integral __denom) {
_Integral __r = __num / __denom;
if (__num % __denom)
++__r;
@@ -77,29 +77,31 @@ class chunk_view : public view_interface<chunk_view<_View>> {
_LIBCPP_ASSERT_PEDANTIC(__n > 0, "Trying to construct a chunk_view with chunk size <= 0");
}
- _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
+ [[nodiscard]] _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_); }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
- _LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator begin() {
+ [[nodiscard]] _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; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept {
+ return std::default_sentinel;
+ }
- _LIBCPP_HIDE_FROM_ABI constexpr auto size()
+ [[nodiscard]] _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
+ [[nodiscard]] _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_));
@@ -125,7 +127,7 @@ class chunk_view<_View>::__outer_iterator {
_LIBCPP_HIDE_FROM_ABI __outer_iterator& operator=(__outer_iterator&&) = default;
- _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const {
+ [[nodiscard]] _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_);
}
@@ -142,7 +144,8 @@ class chunk_view<_View>::__outer_iterator {
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)
+ [[nodiscard]] _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_;
@@ -151,7 +154,8 @@ class chunk_view<_View>::__outer_iterator {
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)
+ [[nodiscard]] _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);
@@ -168,11 +172,13 @@ class chunk_view<_View>::__outer_iterator::value_type : public view_interface<va
_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_); }
+ [[nodiscard]] _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; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept { return default_sentinel; }
- _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
requires sized_sentinel_for<sentinel_t<_View>, iterator_t<_View>>
{
return std::__to_unsigned_like(
@@ -199,9 +205,9 @@ class chunk_view<_View>::__inner_iterator {
_LIBCPP_HIDE_FROM_ABI __inner_iterator& operator=(__inner_iterator&&) = default;
- _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_View> base() const& { return *__parent_->__current_; }
+ [[nodiscard]] _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 {
+ [[nodiscard]] _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_;
}
@@ -217,23 +223,26 @@ class chunk_view<_View>::__inner_iterator {
_LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; }
- _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __inner_iterator& __i, default_sentinel_t) {
+ [[nodiscard]] _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)
+ [[nodiscard]] _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)
+ [[nodiscard]] _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
+ [[nodiscard]] _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_);
}
@@ -262,27 +271,27 @@ class chunk_view<_View> : public view_interface<chunk_view<_View>> {
_LIBCPP_ASSERT_PEDANTIC(__n > 0, "Trying to construct a chunk_view with chunk size <= 0");
}
- _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
+ [[nodiscard]] _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_); }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
- _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
+ [[nodiscard]] _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
+ [[nodiscard]] _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()
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end()
requires(!__simple_view<_View>)
{
if constexpr (common_range<_View> && sized_range<_View>) {
@@ -294,7 +303,7 @@ class chunk_view<_View> : public view_interface<chunk_view<_View>> {
return default_sentinel;
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
requires forward_range<const _View>
{
if constexpr (common_range<const _View> && sized_range<const _View>) {
@@ -306,13 +315,13 @@ class chunk_view<_View> : public view_interface<chunk_view<_View>> {
return default_sentinel;
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto size()
+ [[nodiscard]] _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
+ [[nodiscard]] _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_));
@@ -337,7 +346,7 @@ class chunk_view<_View>::__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() {
+ [[nodiscard]] static consteval auto __get_iterator_concept() {
if constexpr (random_access_range<_Base>)
return random_access_iterator_tag{};
else if constexpr (bidirectional_range<_Base>)
@@ -362,14 +371,14 @@ class chunk_view<_View>::__iterator {
__n_(__i.__n_),
__missing_(__i.__missing_) {}
- _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() const { return __current_; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() const { return __current_; }
- _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const {
+ [[nodiscard]] _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
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr value_type operator[](difference_type __pos) const
requires random_access_range<_Base>
{
return *(*this + __pos);
@@ -422,45 +431,46 @@ class chunk_view<_View>::__iterator {
return *this += -__x;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) {
return __x.__current_ == __y.__current_;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, default_sentinel_t) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, default_sentinel_t) {
return __x.__current_ == __x.__end_;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __x.__current_ < __y.__current_;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __y < __x;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return !(__y < __x);
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return !(__x < __y);
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>>
{
return __x.__current_ <=> __y.__current_;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __i, difference_type __pos)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator
+ operator+(const __iterator& __i, difference_type __pos)
requires random_access_range<_Base>
{
auto __r = __i;
@@ -468,7 +478,8 @@ class chunk_view<_View>::__iterator {
return __r;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __pos, const __iterator& __i)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator
+ operator+(difference_type __pos, const __iterator& __i)
requires random_access_range<_Base>
{
auto __r = __i;
@@ -476,7 +487,8 @@ class chunk_view<_View>::__iterator {
return __r;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __i, difference_type __pos)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator
+ operator-(const __iterator& __i, difference_type __pos)
requires random_access_range<_Base>
{
auto __r = __i;
@@ -484,19 +496,22 @@ class chunk_view<_View>::__iterator {
return __r;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __i, const __iterator& __j)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
+ operator-(const __iterator& __i, const __iterator& __j)
requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>
{
return (__i.__current_ - __j.__current_ + __i.__missing_ - __j.__missing_) / __i.__n_;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(default_sentinel_t, const __iterator& __i)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
+ operator-(default_sentinel_t, const __iterator& __i)
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
{
return ranges::__div_ceil(__i.__end_ - __i.__current_, __i.__n_);
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __i, default_sentinel_t __s)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
+ operator-(const __iterator& __i, default_sentinel_t __s)
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>>
{
return -(__s - __i);
@@ -515,9 +530,9 @@ struct __fn {
template <viewable_range _Range>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto
operator()(_Range&& __range, range_difference_t<_Range> __n) noexcept(
- noexcept(/**/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n))))
+ noexcept(/*-----*/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n))))
-> decltype(/*--*/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n))) {
- return /*-------------*/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n));
+ return /*---------*/ chunk_view(std::forward<_Range>(__range), std::forward<range_difference_t<_Range>>(__n));
}
template <class _DifferenceType>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/types.h b/libcxx/test/std/ranges/range.adaptors/range.chunk/types.h
index 78d41a8ec3665..5c6f3ef21ddb8 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/types.h
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/types.h
@@ -9,7 +9,6 @@
#ifndef TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_CHUNK_TYPES_H
#define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_CHUNK_TYPES_H
-#include <forward_list>
#include <ranges>
#include <vector>
>From 2f19c922db4b43f2b77c3950b8f17e84c7d07bd7 Mon Sep 17 00:00:00 2001
From: anonymouspc <shyeyian at petalmail.com>
Date: Tue, 9 Dec 2025 12:01:09 +0800
Subject: [PATCH 05/11] nodiscard tests
---
.../deref.nodiscard.verify.cpp | 26 +++++++++++++++
.../eq.nodiscard.verify.cpp | 28 ++++++++++++++++
.../iter_move.nodiscard.verify.cpp | 26 +++++++++++++++
.../adaptor.nodiscard.verify.cpp | 31 +++++++++++++++++
.../eq.nodiscard.verify.cpp | 33 +++++++++++++++++++
.../base.nodiscard.verify.cpp | 28 ++++++++++++++++
.../begin.nodiscard.verify.cpp | 26 +++++++++++++++
.../range.chunk.view/end.nodiscard.verify.cpp | 26 +++++++++++++++
8 files changed, 224 insertions(+)
create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/deref.nodiscard.verify.cpp
create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/eq.nodiscard.verify.cpp
create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/iter_move.nodiscard.verify.cpp
create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.overview/adaptor.nodiscard.verify.cpp
create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.sentinel/eq.nodiscard.verify.cpp
create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/base.nodiscard.verify.cpp
create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/begin.nodiscard.verify.cpp
create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/deref.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/deref.nodiscard.verify.cpp
new file mode 100644
index 0000000000000..f62c42e5259dd
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/deref.nodiscard.verify.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// <ranges>
+
+// Test the libc++ extension that std::ranges::chunk_view::iterator<Const>::operator* is marked as [[nodiscard]].
+
+#include <ranges>
+#include <utility>
+
+void test() {
+ char range[6] = {'x', 'x', 'y', 'y', 'z', 'z'};
+ auto view = range | std::views::chunk(2);
+
+ // clang-format off
+ *view.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ *std::as_const(view).begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ // clang-format on
+}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/eq.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/eq.nodiscard.verify.cpp
new file mode 100644
index 0000000000000..fdcf17a0c8155
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/eq.nodiscard.verify.cpp
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// <ranges>
+
+// Test the libc++ extension that std::ranges::chunk_view::iterator<Const>::operator== is marked as [[nodiscard]].
+
+#include <ranges>
+#include <utility>
+
+void test() {
+ char16_t range[3] = {u'x', u'y', u'z'};
+ auto view = range | std::views::chunk(3);
+
+ // clang-format off
+ (view.begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ (std::as_const(view).begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ (view.begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ (std::as_const(view).begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ // clang-format on
+}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/iter_move.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/iter_move.nodiscard.verify.cpp
new file mode 100644
index 0000000000000..f5e26938094fd
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/iter_move.nodiscard.verify.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// <ranges>
+
+// Test the libc++ extension that std::ranges::chunk::iterator<Const>::iter_move is marked as [[nodiscard]].
+
+#include <ranges>
+#include <utility>
+
+void test() {
+ long range[2] = {0L, 2L};
+ auto view = range | std::views::chunk(1);
+
+ // clang-format off
+ std::ranges::iter_move(view.begin()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::ranges::iter_move(std::as_const(view).begin()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ // clang-format on
+}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.overview/adaptor.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.overview/adaptor.nodiscard.verify.cpp
new file mode 100644
index 0000000000000..0bf8e2f99633e
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.overview/adaptor.nodiscard.verify.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// <ranges>
+
+// Test the libc++ extension that std::views::chunk is marked as [[nodiscard]].
+
+#include <ranges>
+
+void test() {
+ int range[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+ // clang-format off
+ std::views::chunk(3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::chunk(range, 3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ range | std::views::chunk(3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::reverse | std::views::chunk(3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ std::views::chunk(3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::chunk(range, 3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ range | std::views::chunk(3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::reverse | std::views::chunk(3); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ // clang-format on
+}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.sentinel/eq.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.sentinel/eq.nodiscard.verify.cpp
new file mode 100644
index 0000000000000..41e2072640641
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.sentinel/eq.nodiscard.verify.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// <ranges>
+
+// Test the libc++ extension that std::ranges::chunk_view::sentinel<Const>::operator== is marked as [[nodiscard]].
+
+#include <array>
+#include <ranges>
+#include <utility>
+
+#include "test_iterators.h"
+#include "test_range.h"
+
+void test() {
+ int range[6] = {1, 3, 4, 6, 7, 9};
+
+ std::ranges::chunk_view view(range, 2);
+
+ // clang-format off
+ (view.begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ (std::as_const(view).begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ (view.begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ (std::as_const(view).begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ // clang-format on
+}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/base.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/base.nodiscard.verify.cpp
new file mode 100644
index 0000000000000..9f2d946d173f2
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/base.nodiscard.verify.cpp
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// <ranges>
+
+// Test the libc++ extension that std::ranges:chunk_view::base is marked as [[nodiscard]].
+
+#include <ranges>
+#include <utility>
+
+void test() {
+ int range[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ auto view = range | std::views::chunk(3);
+
+ // clang-format off
+ view.base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(view).base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::move(std::as_const(view)).base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::move(view).base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ // clang-format on
+}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/begin.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/begin.nodiscard.verify.cpp
new file mode 100644
index 0000000000000..ba9520dff23a3
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/begin.nodiscard.verify.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// <ranges>
+
+// Test the libc++ extension that std::ranges::chunk_view::begin is marked as [[nodiscard]].
+
+#include <ranges>
+#include <utility>
+
+void test() {
+ int range[6] = {1, 3, 4, 6, 7, 9};
+ auto view = range | std::views::chunk(3);
+
+ // clang-format off
+ view.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(view).begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ // clang-format on
+}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp
new file mode 100644
index 0000000000000..124fe707ac41e
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// <ranges>
+
+// Test the libc++ extension that std::ranges::chunk_view::end is marked as [[nodiscard]].
+
+#include <ranges>
+#include <utility>
+
+void test() {
+ int range[6] = {1, 2, 4, 5, 7, 8};
+ auto view = range | std::views::chunk(3);
+
+ // clang-format off
+ view.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ td::as_const(view).end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ // clang-format on
+}
>From 09f85db75b0d1113efbf75c8d9b7e0376ba60ecc Mon Sep 17 00:00:00 2001
From: anonymouspc <shyeyian at petalmail.com>
Date: Tue, 9 Dec 2025 12:01:17 +0800
Subject: [PATCH 06/11] no_unique_address tests
---
.../no_unique_address.compile.pass.cpp | 55 +++++++++++++++++++
1 file changed, 55 insertions(+)
create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/no_unique_address.compile.pass.cpp
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/no_unique_address.compile.pass.cpp
new file mode 100644
index 0000000000000..2b7e8effcc59e
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/no_unique_address.compile.pass.cpp
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// XFAIL: msvc
+
+// <ranges>
+
+// This test ensures that we use `[[no_unique_address]]` in `chunk_view`.
+
+#include <cstddef>
+#include <iostream>
+#include <ranges>
+#include <string>
+#include <type_traits>
+
+#include "test_iterators.h"
+#include "test_range.h"
+
+using input_view = std::views::all_t<test_range<cpp20_input_iterator>>;
+static_assert(std::ranges::input_range<input_view> && !std::ranges::forward_range<input_view>);
+
+struct forward_view : std::ranges::view_base {
+ std::string* begin() const;
+ std::string* end() const;
+};
+static_assert(std::ranges::forward_range<forward_view>);
+static_assert(std::is_reference_v<std::ranges::range_reference_t<forward_view>>);
+
+template <class View>
+struct Test {
+ [[no_unique_address]] View view;
+ unsigned char pad;
+};
+
+using CV1 = std::ranges::chunk_view<input_view>;
+// Expected CV1 (with View == input) layout:
+// [[no_unique_address]] _View __base_ // offset: 0
+// [[no_unique_address]] range_difference_t<_View> __n_ // offset: sizeof(std::ptrdiff_t)
+// [[no_unique_address]] range_difference_t<_View> __remainder_ // offset: sizeof(std::ptrdiff_t)
+// [[no_unique_address]] __non_propagating_cache<iterator_t<_View>> __current_ // offset: ?
+// TODO: how to test this ?
+
+using CV2 = std::ranges::chunk_view<forward_view>;
+// Expected CV2 (with View >= forward) layout:
+// [[no_unique_address]] _View __base_ // offset: 0
+// [[no_unique_address]] range_difference_t<_View> // offset: sizeof(std::ptrdiff_t)
+static_assert(sizeof(CV2) == sizeof(std::ptrdiff_t));
+static_assert(sizeof(Test<CV2>) == sizeof(std::ptrdiff_t) * 2);
>From a33c1be53aa771927656e4ed625d8c0ba83563ae Mon Sep 17 00:00:00 2001
From: anonymouspc <shyeyian at petalmail.com>
Date: Tue, 9 Dec 2025 12:01:54 +0800
Subject: [PATCH 07/11] clang-format
---
.../range.chunk.iterator/deref.nodiscard.verify.cpp | 2 +-
.../range.chunk/range.chunk.iterator/eq.nodiscard.verify.cpp | 2 +-
.../range.chunk.iterator/iter_move.nodiscard.verify.cpp | 4 ++--
.../range.chunk/range.chunk.view/base.nodiscard.verify.cpp | 2 +-
.../range.chunk/range.chunk.view/begin.nodiscard.verify.cpp | 2 +-
.../range.chunk/range.chunk.view/end.nodiscard.verify.cpp | 2 +-
6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/deref.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/deref.nodiscard.verify.cpp
index f62c42e5259dd..d3722f961234c 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/deref.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/deref.nodiscard.verify.cpp
@@ -17,7 +17,7 @@
void test() {
char range[6] = {'x', 'x', 'y', 'y', 'z', 'z'};
- auto view = range | std::views::chunk(2);
+ auto view = range | std::views::chunk(2);
// clang-format off
*view.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/eq.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/eq.nodiscard.verify.cpp
index fdcf17a0c8155..d743d1e7c40d3 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/eq.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/eq.nodiscard.verify.cpp
@@ -17,7 +17,7 @@
void test() {
char16_t range[3] = {u'x', u'y', u'z'};
- auto view = range | std::views::chunk(3);
+ auto view = range | std::views::chunk(3);
// clang-format off
(view.begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/iter_move.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/iter_move.nodiscard.verify.cpp
index f5e26938094fd..b1f13ae6ee14f 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/iter_move.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.iterator/iter_move.nodiscard.verify.cpp
@@ -17,8 +17,8 @@
void test() {
long range[2] = {0L, 2L};
- auto view = range | std::views::chunk(1);
-
+ auto view = range | std::views::chunk(1);
+
// clang-format off
std::ranges::iter_move(view.begin()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::ranges::iter_move(std::as_const(view).begin()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/base.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/base.nodiscard.verify.cpp
index 9f2d946d173f2..ecd0d92aa861e 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/base.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/base.nodiscard.verify.cpp
@@ -17,7 +17,7 @@
void test() {
int range[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
- auto view = range | std::views::chunk(3);
+ auto view = range | std::views::chunk(3);
// clang-format off
view.base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/begin.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/begin.nodiscard.verify.cpp
index ba9520dff23a3..02e7fc8a2686c 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/begin.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/begin.nodiscard.verify.cpp
@@ -17,7 +17,7 @@
void test() {
int range[6] = {1, 3, 4, 6, 7, 9};
- auto view = range | std::views::chunk(3);
+ auto view = range | std::views::chunk(3);
// clang-format off
view.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp
index 124fe707ac41e..dd011bb47770a 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp
@@ -17,7 +17,7 @@
void test() {
int range[6] = {1, 2, 4, 5, 7, 8};
- auto view = range | std::views::chunk(3);
+ auto view = range | std::views::chunk(3);
// clang-format off
view.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
>From 5704a7ba02aa8ab78219b6529e03c588a4aadc08 Mon Sep 17 00:00:00 2001
From: anonymouspc <shyeyian at petalmail.com>
Date: Tue, 9 Dec 2025 12:09:32 +0800
Subject: [PATCH 08/11] list is not constexpr until C++26, thus not testable in
C++23
---
.../range.chunk.view/end.nodiscard.verify.cpp | 2 +-
.../range.adaptors/range.chunk/begin.pass.cpp | 26 +++++++++---------
.../range.adaptors/range.chunk/end.pass.cpp | 27 ++++++++-----------
3 files changed, 25 insertions(+), 30 deletions(-)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp
index dd011bb47770a..ba3c75376c526 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.chunk/range.chunk.view/end.nodiscard.verify.cpp
@@ -21,6 +21,6 @@ void test() {
// clang-format off
view.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- td::as_const(view).end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(view).end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
// clang-format on
}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
index 5a55d1e343139..c90c1543dd43f 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
@@ -14,41 +14,41 @@
#include <algorithm>
#include <cassert>
-#include <list>
+#include <vector>
#include "test_range.h"
constexpr bool test() {
- std::list<int> full_list = {1, 1, 1, 2, 2, 2, 3, 3};
- std::list<int> empty_list = {};
+ std::vector<int> full_vector = {1, 1, 1, 2, 2, 2, 3, 3};
+ std::vector<int> empty_vector = {};
// Test `chunk_view.begin()`
{
- auto view = full_list | std::views::chunk(3);
+ auto view = full_vector | std::views::chunk(3);
auto it = view.begin();
- assert(std::ranges::equal(*it, std::list{1, 1, 1}));
- assert(std::ranges::equal(*++it, std::list{2, 2, 2}));
- assert(std::ranges::equal(*++it, std::list{3, 3})); // The last chunk has only 2 elements.
+ assert(std::ranges::equal(*it, std::vector{1, 1, 1}));
+ assert(std::ranges::equal(*++it, std::vector{2, 2, 2}));
+ assert(std::ranges::equal(*++it, std::vector{3, 3})); // The last chunk has only 2 elements.
assert(++it == view.end()); // Reaches end.
- view = full_list | std::views::chunk(5);
+ view = full_vector | std::views::chunk(5);
it = view.begin();
- assert(std::ranges::equal(*it, std::list{1, 1, 1, 2, 2}));
- assert(std::ranges::equal(*++it, std::list{2, 3, 3}));
+ assert(std::ranges::equal(*it, std::vector{1, 1, 1, 2, 2}));
+ assert(std::ranges::equal(*++it, std::vector{2, 3, 3}));
}
// Test `empty_chunk_view.begin()`
{
- auto view = empty_list | std::views::chunk(3);
+ auto view = empty_vector | std::views::chunk(3);
assert(view.size() == 0);
assert(view.begin() == view.end());
}
// Test `small_view_with_big_chunk.begin()`
{
- auto view = full_list | std::views::chunk(314159);
+ auto view = full_vector | std::views::chunk(314159);
assert(view.size() == 1);
- assert(std::ranges::equal(*view.begin(), full_list));
+ assert(std::ranges::equal(*view.begin(), full_vector));
assert(++view.begin() == view.end());
}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp
index ccd136ab193a0..affb5074e3885 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/end.pass.cpp
@@ -15,41 +15,36 @@
#include <algorithm>
#include <cassert>
#include <concepts>
-#include <forward_list>
-#include <list>
+#include <vector>
#include "test_range.h"
#include "types.h"
constexpr bool test() {
- std::list list = {1, 1, 1, 2, 2, 2, 3, 3};
- std::forward_list forward_list = {1, 1, 1, 2, 2, 2, 3, 3};
+ std::vector vector = {1, 1, 1, 2, 2, 2, 3, 3};
// Test `chunk_view.end()`
{
- auto view = list | std::views::chunk(3);
+ auto view = vector | std::views::chunk(3);
auto it = view.end();
- assert(std::ranges::equal(*--it, std::list{3, 3})); // We can adjust the tailing chunk-size.
- assert(std::ranges::equal(*--it, std::list{2, 2, 2}));
- assert(std::ranges::equal(*--it, std::list{1, 1, 1}));
+ assert(std::ranges::equal(*--it, std::vector{3, 3})); // We can adjust the tailing chunk-size.
+ assert(std::ranges::equal(*--it, std::vector{2, 2, 2}));
+ assert(std::ranges::equal(*--it, std::vector{1, 1, 1}));
}
// Test `not_sized_chunk_view.end()`
{
- auto not_sized_list = not_sized_view(list | std::views::all);
- auto view = not_sized_list | std::views::chunk(4);
+ auto not_sized_vector = not_sized_view(vector | std::views::all);
+ auto view = not_sized_vector | std::views::chunk(4);
static_assert(std::ranges::bidirectional_range<decltype(view)>);
static_assert(!std::ranges::sized_range<decltype(view)>);
- static_assert(
- std::same_as<
- decltype(view.end()),
- std::
- default_sentinel_t>); // We cannot handle the tailing chunk without size info, so we forbids one to derement from end().
+ // We cannot handle the tailing chunk without size info, so we forbids one to derement from end().
+ static_assert(std::same_as< decltype(view.end()), std::default_sentinel_t>);
}
// Test `forward_chunk_view.end()`
{
- auto view = list | std::views::chunk(5);
+ auto view = vector | std::views::chunk(5);
assert(++(++view.begin()) == view.end());
}
>From 0bce4e1925d2ecb6f26d149641a107e597256f8e Mon Sep 17 00:00:00 2001
From: anonymouspc <shyeyian at petalmail.com>
Date: Tue, 9 Dec 2025 12:11:45 +0800
Subject: [PATCH 09/11] clang-format
---
.../test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
index c90c1543dd43f..5c8951f3bb10e 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/begin.pass.cpp
@@ -29,7 +29,7 @@ constexpr bool test() {
assert(std::ranges::equal(*it, std::vector{1, 1, 1}));
assert(std::ranges::equal(*++it, std::vector{2, 2, 2}));
assert(std::ranges::equal(*++it, std::vector{3, 3})); // The last chunk has only 2 elements.
- assert(++it == view.end()); // Reaches end.
+ assert(++it == view.end()); // Reaches end.
view = full_vector | std::views::chunk(5);
it = view.begin();
>From 202a86cd4ad8d01205c6c33c52579dfe64bd81de Mon Sep 17 00:00:00 2001
From: anonymous <shyeyian at icloud.com>
Date: Tue, 9 Dec 2025 12:35:08 +0800
Subject: [PATCH 10/11] Apply suggestion from @H-G-Hristov
Co-authored-by: Hristo Hristov <hghristov.rmm at gmail.com>
---
.../range.adaptors/range.chunk/ctad.compile.pass.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp
index ed04cd57555ff..862accc4063b1 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk/ctad.compile.pass.cpp
@@ -39,10 +39,10 @@ void testCTAD() {
static_assert(std::same_as< decltype(std::ranges::chunk_view(std::move(v), 0)), std::ranges::chunk_view<view> >);
static_assert(
std::same_as< decltype(std::ranges::chunk_view(r, 0)), std::ranges::chunk_view<std::ranges::ref_view<range>> >);
- static_assert(std::same_as< decltype(std::ranges::chunk_view(std::move(r), 0)),
- std::ranges::chunk_view<std::ranges::owning_view<range>> >);
- static_assert(std::same_as< decltype(std::ranges::chunk_view(br, 0)),
- std::ranges::chunk_view<std::ranges::ref_view<borrowed_range>> >);
- static_assert(std::same_as< decltype(std::ranges::chunk_view(std::move(br), 0)),
- std::ranges::chunk_view<std::ranges::owning_view<borrowed_range>> >);
+ static_assert(std::same_as<decltype(std::ranges::chunk_view(std::move(r), 0)),
+ std::ranges::chunk_view<std::ranges::owning_view<range>>>);
+ static_assert(std::same_as<decltype(std::ranges::chunk_view(br, 0)),
+ std::ranges::chunk_view<std::ranges::ref_view<borrowed_range>>>);
+ static_assert(std::same_as<decltype(std::ranges::chunk_view(std::move(br), 0)),
+ std::ranges::chunk_view<std::ranges::owning_view<borrowed_range>>>);
}
>From c338deeb38899e8562c011537d8f7ee6f3e197bb Mon Sep 17 00:00:00 2001
From: anonymouspc <shyeyian at petalmail.com>
Date: Tue, 9 Dec 2025 12:54:18 +0800
Subject: [PATCH 11/11] revert BUILD.gn
---
llvm/utils/gn/secondary/libcxx/include/BUILD.gn | 1 -
1 file changed, 1 deletion(-)
diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
index 16be8fa8de795..9755fe3a7ea50 100644
--- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
+++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
@@ -1352,7 +1352,6 @@ if (current_toolchain == default_toolchain) {
"__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",
More information about the llvm-commits
mailing list