[libcxx-commits] [libcxx] [libc++] Partially implement P2846R6: `reserve_hint` (PR #206385)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Jun 28 18:19:48 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: inquisitivecrystal (inquisitivecrystal)

<details>
<summary>Changes</summary>

This implements a substantial portion of [P2846R6](wg21.link/P2846R6), including:
- the `ranges::reserve_hint` CPO
- the `approximately_sized_range` concept
- the `<adaptor>::reserve_hint` member functions for all current range adaptors

The major gap in coverage is that this change does not adjust containers to actually use the provided reserve hints in their range-based constructors and functions. I found that change to be quite complicated, since it ends up involving tweaking the internals of almost every container. The current change also seemed like quite a large chunk to review at once even without adding the container modifications, so I thought it made sense to break it off as a separate piece.

A secondary gap is that this does not add `reserve_hint` members for `chunk_view`, `slide_view`, and `as_const_view`, because these adaptors haven't been added to libc++ yet.

Assisted-by: Claude Code
I wrote the core implementation and the range.access tests entirely by hand, but had Claude write a little over half of the range.adaptor tests after I realized how repetitive they were. I have reviewed and edited all of the generated tests.

Part of #<!-- -->127884.
Resolves #<!-- -->189881.

---

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


41 Files Affected:

- (modified) libcxx/docs/Status/Cxx26Issues.csv (+1-1) 
- (modified) libcxx/docs/Status/Cxx26Papers.csv (+1-1) 
- (modified) libcxx/include/__ranges/adjacent_transform_view.h (+16) 
- (modified) libcxx/include/__ranges/adjacent_view.h (+24) 
- (modified) libcxx/include/__ranges/as_rvalue_view.h (+16) 
- (modified) libcxx/include/__ranges/common_view.h (+16) 
- (modified) libcxx/include/__ranges/concat_view.h (+22) 
- (modified) libcxx/include/__ranges/concepts.h (+14) 
- (modified) libcxx/include/__ranges/drop_view.h (+18) 
- (modified) libcxx/include/__ranges/elements_view.h (+16) 
- (modified) libcxx/include/__ranges/enumerate_view.h (+16) 
- (modified) libcxx/include/__ranges/owning_view.h (+16) 
- (modified) libcxx/include/__ranges/ref_view.h (+9) 
- (modified) libcxx/include/__ranges/reverse_view.h (+16) 
- (modified) libcxx/include/__ranges/size.h (+53) 
- (modified) libcxx/include/__ranges/stride_view.h (+19) 
- (modified) libcxx/include/__ranges/take_view.h (+20) 
- (modified) libcxx/include/__ranges/transform_view.h (+16) 
- (modified) libcxx/include/ranges (+5) 
- (modified) libcxx/modules/std/ranges.inc (+9) 
- (added) libcxx/test/std/ranges/range.access/reserve_hint.pass.cpp (+100) 
- (added) libcxx/test/std/ranges/range.access/reserve_hint.verify.cpp (+21) 
- (added) libcxx/test/std/ranges/range.adaptors/range.adjacent.transform/reserve_hint.pass.cpp (+130) 
- (added) libcxx/test/std/ranges/range.adaptors/range.adjacent/reserve_hint.pass.cpp (+108) 
- (added) libcxx/test/std/ranges/range.adaptors/range.all/range.owning.view/reserve_hint.pass.cpp (+86) 
- (modified) libcxx/test/std/ranges/range.adaptors/range.all/range.ref.view/range.ref.view.pass.cpp (+29) 
- (added) libcxx/test/std/ranges/range.adaptors/range.as.rvalue/reserve_hint.pass.cpp (+90) 
- (added) libcxx/test/std/ranges/range.adaptors/range.common.view/reserve_hint.pass.cpp (+63) 
- (modified) libcxx/test/std/ranges/range.adaptors/range.common.view/types.h (+31) 
- (added) libcxx/test/std/ranges/range.adaptors/range.concat/reserve_hint.pass.cpp (+107) 
- (added) libcxx/test/std/ranges/range.adaptors/range.drop/reserve_hint.pass.cpp (+59) 
- (modified) libcxx/test/std/ranges/range.adaptors/range.drop/types.h (+14) 
- (added) libcxx/test/std/ranges/range.adaptors/range.elements/reserve_hint.pass.cpp (+90) 
- (added) libcxx/test/std/ranges/range.adaptors/range.enumerate/reserve_hint.pass.cpp (+82) 
- (added) libcxx/test/std/ranges/range.adaptors/range.reverse/reserve_hint.pass.cpp (+89) 
- (added) libcxx/test/std/ranges/range.adaptors/range.stride.view/reserve_hint.pass.cpp (+99) 
- (modified) libcxx/test/std/ranges/range.adaptors/range.stride.view/types.h (+15-4) 
- (added) libcxx/test/std/ranges/range.adaptors/range.take/reserve_hint.pass.cpp (+87) 
- (modified) libcxx/test/std/ranges/range.adaptors/range.take/types.h (+14) 
- (added) libcxx/test/std/ranges/range.adaptors/range.transform/reserve_hint.pass.cpp (+44) 
- (modified) libcxx/test/std/ranges/range.adaptors/range.transform/types.h (+33) 


``````````diff
diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index d4f7a44910e00..804cb2580411f 100644
--- a/libcxx/docs/Status/Cxx26Issues.csv
+++ b/libcxx/docs/Status/Cxx26Issues.csv
@@ -336,7 +336,7 @@
 "`LWG4549 <https://wg21.link/LWG4549>`__","``vprint_nonunicode_buffered`` ignores its stream parameter","2026-03 (Croydon)","","","`#189878 <https://github.com/llvm/llvm-project/issues/189878>`__",""
 "`LWG4550 <https://wg21.link/LWG4550>`__","Need new feature test macros for ``<stdckdint.h>`` and ``<stdbit.h>``","2026-03 (Croydon)","","","`#189879 <https://github.com/llvm/llvm-project/issues/189879>`__",""
 "`LWG4552 <https://wg21.link/LWG4552>`__","``compare_exchange_weak`` writes a value on spurious failure, not memory contents","2026-03 (Croydon)","","","`#189880 <https://github.com/llvm/llvm-project/issues/189880>`__",""
-"`LWG4553 <https://wg21.link/LWG4553>`__","Wording for FR-025-246 25.7.18.2 Add a ``reserve_hint`` function to ``concat_view``","2026-03 (Croydon)","","","`#189881 <https://github.com/llvm/llvm-project/issues/189881>`__",""
+"`LWG4553 <https://wg21.link/LWG4553>`__","Wording for FR-025-246 25.7.18.2 Add a ``reserve_hint`` function to ``concat_view``","2026-03 (Croydon)","|Complete|","23","`#189881 <https://github.com/llvm/llvm-project/issues/189881>`__",""
 "`LWG4554 <https://wg21.link/LWG4554>`__","Remove undefined behaviour from ``hive`` for invalid limits","2026-03 (Croydon)","","","`#189882 <https://github.com/llvm/llvm-project/issues/189882>`__",""
 "`LWG4555 <https://wg21.link/LWG4555>`__","Remove ``is_consteval_only``","2026-03 (Croydon)","","","`#189883 <https://github.com/llvm/llvm-project/issues/189883>`__",""
 "`LWG4556 <https://wg21.link/LWG4556>`__","Unclear properties of reflection strings","2026-03 (Croydon)","","","`#189884 <https://github.com/llvm/llvm-project/issues/189884>`__",""
diff --git a/libcxx/docs/Status/Cxx26Papers.csv b/libcxx/docs/Status/Cxx26Papers.csv
index 9744940459bcd..f4d57a47a0c8f 100644
--- a/libcxx/docs/Status/Cxx26Papers.csv
+++ b/libcxx/docs/Status/Cxx26Papers.csv
@@ -112,7 +112,7 @@
 "`P3430R3 <https://wg21.link/P3430R3>`__","simd issues: explicit, unsequenced, identity-element position, and members of disabled simd","2025-02 (Hagenberg)","","","`#127881 <https://github.com/llvm/llvm-project/issues/127881>`__",""
 "`P2663R7 <https://wg21.link/P2663R7>`__","Interleaved complex values support in ``std::simd``","2025-02 (Hagenberg)","","","`#127882 <https://github.com/llvm/llvm-project/issues/127882>`__",""
 "`P2933R4 <https://wg21.link/P2933R4>`__","Extend ``<bit>`` header function with overloads for ``std::simd``","2025-02 (Hagenberg)","","","`#127883 <https://github.com/llvm/llvm-project/issues/127883>`__",""
-"`P2846R6 <https://wg21.link/P2846R6>`__","``reserve_hint``: Eagerly reserving memory for not-quite-sized lazy ranges","2025-02 (Hagenberg)","","","`#127884 <https://github.com/llvm/llvm-project/issues/127884>`__",""
+"`P2846R6 <https://wg21.link/P2846R6>`__","``reserve_hint``: Eagerly reserving memory for not-quite-sized lazy ranges","2025-02 (Hagenberg)","|Partial|","23","`#127884 <https://github.com/llvm/llvm-project/issues/127884>`__","``__cpp_lib_ranges_reserve_hint`` is not set. Container operations that take a range as input do not respect ``reserve_hint``. ``chunk_view`` and ``slide_view`` support blocked on `P2442R1 <https://wg21.link/P2442R1>`__. ``as_const_view`` support blocked on `P2278R4 <https://wg21.link/P2278R4>`__."
 "`P3471R4 <https://wg21.link/P3471R4>`__","Standard Library Hardening","2025-02 (Hagenberg)","","","`#127885 <https://github.com/llvm/llvm-project/issues/127885>`__",""
 "`P0447R28 <https://wg21.link/P0447R28>`__","Introduction of ``std::hive`` to the standard library","2025-02 (Hagenberg)","","","`#127886 <https://github.com/llvm/llvm-project/issues/127886>`__",""
 "`P3019R14 <https://wg21.link/P3019R14>`__","``indirect`` and ``polymorphic``: Vocabulary Types for Composite Class Design","2025-02 (Hagenberg)","","","`#127887 <https://github.com/llvm/llvm-project/issues/127887>`__",""
diff --git a/libcxx/include/__ranges/adjacent_transform_view.h b/libcxx/include/__ranges/adjacent_transform_view.h
index 4863d074482dc..e7e05539e8aaa 100644
--- a/libcxx/include/__ranges/adjacent_transform_view.h
+++ b/libcxx/include/__ranges/adjacent_transform_view.h
@@ -149,6 +149,22 @@ class adjacent_transform_view : public view_interface<adjacent_transform_view<_V
   {
     return __inner_.size();
   }
+
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires approximately_sized_range<_InnerView>
+  {
+    return __inner_.reserve_hint();
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires approximately_sized_range<const _InnerView>
+  {
+    return __inner_.reserve_hint();
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
 };
 
 template <forward_range _View, move_constructible _Fn, size_t _Np>
diff --git a/libcxx/include/__ranges/adjacent_view.h b/libcxx/include/__ranges/adjacent_view.h
index 40474b85c794f..27b116e30eee9 100644
--- a/libcxx/include/__ranges/adjacent_view.h
+++ b/libcxx/include/__ranges/adjacent_view.h
@@ -139,6 +139,30 @@ class adjacent_view : public view_interface<adjacent_view<_View, _Np>> {
     __sz -= std::min<_CT>(__sz, _Np - 1);
     return static_cast<_ST>(__sz);
   }
+
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires approximately_sized_range<_View>
+  {
+    using _ST = decltype(ranges::reserve_hint(__base_));
+    using _CT = common_type_t<_ST, size_t>;
+    auto __sz = static_cast<_CT>(ranges::reserve_hint(__base_));
+    __sz -= std::min<_CT>(__sz, _Np - 1);
+    return static_cast<_ST>(__sz);
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires approximately_sized_range<const _View>
+  {
+    using _ST = decltype(ranges::reserve_hint(__base_));
+    using _CT = common_type_t<_ST, size_t>;
+    auto __sz = static_cast<_CT>(ranges::reserve_hint(__base_));
+    __sz -= std::min<_CT>(__sz, _Np - 1);
+    return static_cast<_ST>(__sz);
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
 };
 
 struct __adjacent_view_iter_access {
diff --git a/libcxx/include/__ranges/as_rvalue_view.h b/libcxx/include/__ranges/as_rvalue_view.h
index a553f39998e0e..705cf559a7ee0 100644
--- a/libcxx/include/__ranges/as_rvalue_view.h
+++ b/libcxx/include/__ranges/as_rvalue_view.h
@@ -99,6 +99,22 @@ class as_rvalue_view : public view_interface<as_rvalue_view<_View>> {
   {
     return ranges::size(__base_);
   }
+
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires approximately_sized_range<_View>
+  {
+    return ranges::reserve_hint(__base_);
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires approximately_sized_range<const _View>
+  {
+    return ranges::reserve_hint(__base_);
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
 };
 
 template <class _Range>
diff --git a/libcxx/include/__ranges/common_view.h b/libcxx/include/__ranges/common_view.h
index eec1045c8a758..4f1dfbf5d9ac2 100644
--- a/libcxx/include/__ranges/common_view.h
+++ b/libcxx/include/__ranges/common_view.h
@@ -101,6 +101,22 @@ class common_view : public view_interface<common_view<_View>> {
   {
     return ranges::size(__base_);
   }
+
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires approximately_sized_range<_View>
+  {
+    return ranges::reserve_hint(__base_);
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires approximately_sized_range<const _View>
+  {
+    return ranges::reserve_hint(__base_);
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
 };
 
 template <class _Range>
diff --git a/libcxx/include/__ranges/concat_view.h b/libcxx/include/__ranges/concat_view.h
index 3bbe9db12e0f8..33d269b9fd09a 100644
--- a/libcxx/include/__ranges/concat_view.h
+++ b/libcxx/include/__ranges/concat_view.h
@@ -176,6 +176,28 @@ class concat_view : public view_interface<concat_view<_Views...>> {
         [](auto... __sizes) { return (make_unsigned_t<common_type_t<decltype(__sizes)...>>(__sizes) + ...); },
         std::__tuple_transform(ranges::size, __views_));
   }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires(approximately_sized_range<_Views> && ...)
+  {
+    return apply(
+        [](auto... __sizes) static {
+          using _CT = make_unsigned_t<common_type_t<decltype(__sizes)...>>;
+          return (_CT(__sizes) + ...);
+        },
+        std::__tuple_transform(ranges::reserve_hint, __views_));
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires(approximately_sized_range<const _Views> && ...)
+  {
+    return apply(
+        [](auto... __sizes) static {
+          using _CT = make_unsigned_t<common_type_t<decltype(__sizes)...>>;
+          return (_CT(__sizes) + ...);
+        },
+        std::__tuple_transform(ranges::reserve_hint, __views_));
+  }
 };
 
 template <class... _Views>
diff --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h
index bf75fe8a6fef4..e7cfc94506120 100644
--- a/libcxx/include/__ranges/concepts.h
+++ b/libcxx/include/__ranges/concepts.h
@@ -80,10 +80,24 @@ using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<_Rp>>;
 template <range _Rp>
 using range_common_reference_t = iter_common_reference_t<iterator_t<_Rp>>;
 
+#  if _LIBCPP_STD_VER >= 26
+
+// [range.approximately.sized]
+template <class _Tp>
+concept approximately_sized_range = range<_Tp> && requires(_Tp& __t) { ranges::reserve_hint(__t); };
+
+// [range.sized]
+template <class _Tp>
+concept sized_range = approximately_sized_range<_Tp> && requires(_Tp& __t) { ranges::size(__t); };
+
+#  else // _LIBCPP_STD_VER < 26
+
 // [range.sized]
 template <class _Tp>
 concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); };
 
+#  endif
+
 template <sized_range _Rp>
 using range_size_t = decltype(ranges::size(std::declval<_Rp&>()));
 
diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h
index e3754e64d536f..9cae5c1c30276 100644
--- a/libcxx/include/__ranges/drop_view.h
+++ b/libcxx/include/__ranges/drop_view.h
@@ -139,6 +139,24 @@ class drop_view : public view_interface<drop_view<_View>> {
   {
     return __size(*this);
   }
+
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires approximately_sized_range<_View>
+  {
+    const auto __s = static_cast<range_difference_t<_View>>(ranges::reserve_hint(__base_));
+    return __to_unsigned_like(__s < __count_ ? 0 : __s - __count_);
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires approximately_sized_range<const _View>
+  {
+    const auto __s = static_cast<range_difference_t<const _View>>(ranges::reserve_hint(__base_));
+    return __to_unsigned_like(__s < __count_ ? 0 : __s - __count_);
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
 };
 
 template <class _Range>
diff --git a/libcxx/include/__ranges/elements_view.h b/libcxx/include/__ranges/elements_view.h
index b1419f2a1dd91..9ce87e6814dbe 100644
--- a/libcxx/include/__ranges/elements_view.h
+++ b/libcxx/include/__ranges/elements_view.h
@@ -133,6 +133,22 @@ class elements_view : public view_interface<elements_view<_View, _Np>> {
     return ranges::size(__base_);
   }
 
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires approximately_sized_range<_View>
+  {
+    return ranges::reserve_hint(__base_);
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires approximately_sized_range<const _View>
+  {
+    return ranges::reserve_hint(__base_);
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
+
 private:
   _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
 };
diff --git a/libcxx/include/__ranges/enumerate_view.h b/libcxx/include/__ranges/enumerate_view.h
index bb7696897af00..1a67a23e864d7 100644
--- a/libcxx/include/__ranges/enumerate_view.h
+++ b/libcxx/include/__ranges/enumerate_view.h
@@ -115,6 +115,22 @@ class enumerate_view : public view_interface<enumerate_view<_View>> {
     return __base_;
   }
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
+
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires approximately_sized_range<_View>
+  {
+    return ranges::reserve_hint(__base_);
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires approximately_sized_range<const _View>
+  {
+    return ranges::reserve_hint(__base_);
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
 };
 
 template <class _Range>
diff --git a/libcxx/include/__ranges/owning_view.h b/libcxx/include/__ranges/owning_view.h
index 1ab81afee774a..b1e8415c3a477 100644
--- a/libcxx/include/__ranges/owning_view.h
+++ b/libcxx/include/__ranges/owning_view.h
@@ -99,6 +99,22 @@ class owning_view : public view_interface<owning_view<_Rp>> {
   {
     return ranges::data(__r_);
   }
+
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires approximately_sized_range<_Rp>
+  {
+    return ranges::reserve_hint(__r_);
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires approximately_sized_range<const _Rp>
+  {
+    return ranges::reserve_hint(__r_);
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
 };
 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(owning_view);
 
diff --git a/libcxx/include/__ranges/ref_view.h b/libcxx/include/__ranges/ref_view.h
index 109a10cec299e..34f129ace54e7 100644
--- a/libcxx/include/__ranges/ref_view.h
+++ b/libcxx/include/__ranges/ref_view.h
@@ -73,6 +73,15 @@ class ref_view : public view_interface<ref_view<_Range>> {
   {
     return ranges::data(*__range_);
   }
+
+#  if _LIBCPP_STD_VER >= 26
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires approximately_sized_range<_Range>
+  {
+    return ranges::reserve_hint(*__range_);
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
 };
 
 template <class _Range>
diff --git a/libcxx/include/__ranges/reverse_view.h b/libcxx/include/__ranges/reverse_view.h
index b016cc231f2b5..fc8e609705661 100644
--- a/libcxx/include/__ranges/reverse_view.h
+++ b/libcxx/include/__ranges/reverse_view.h
@@ -111,6 +111,22 @@ class reverse_view : public view_interface<reverse_view<_View>> {
   {
     return ranges::size(__base_);
   }
+
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires approximately_sized_range<_View>
+  {
+    return ranges::reserve_hint(__base_);
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires approximately_sized_range<const _View>
+  {
+    return ranges::reserve_hint(__base_);
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
 };
 
 template <class _Range>
diff --git a/libcxx/include/__ranges/size.h b/libcxx/include/__ranges/size.h
index 5da3a6ff268e8..3dfeade03fce5 100644
--- a/libcxx/include/__ranges/size.h
+++ b/libcxx/include/__ranges/size.h
@@ -131,6 +131,59 @@ inline constexpr auto ssize = __ssize::__fn{};
 } // namespace __cpo
 } // namespace ranges
 
+#  if _LIBCPP_STD_VER >= 26
+
+// [range.prim.size.hint]
+
+namespace ranges {
+namespace __reserve_hint {
+void reserve_hint() = delete;
+
+template <typename _Tp>
+concept __std_size = requires(_Tp&& __t) { ranges::size(__t); };
+
+template <typename _Tp>
+concept __member_reserve_hint = !__std_size<_Tp> && requires(_Tp&& __t) {
+  { auto(__t.reserve_hint()) } -> __integer_like;
+};
+
+template <typename _Tp>
+concept __freestanding_reserve_hint =
+    !__std_size<_Tp> && !__member_reserve_hint<_Tp> && __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) {
+      { auto(reserve_hint(__t)) } -> __integer_like;
+    };
+
+struct __fn {
+  // `[range.prim.size.hint]`: `std::size(t)` is a valid expression
+  template <__std_size _Tp>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const
+      noexcept(noexcept(ranges::size(__t))) {
+    return ranges::size(__t);
+  }
+
+  // `[range.prim.size.hint]`: `auto(t.reserve_hint())` is a valid expression
+  template <__member_reserve_hint _Tp>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const
+      noexcept(noexcept(auto(__t.reserve_hint()))) {
+    return auto(__t.reserve_hint());
+  }
+
+  // `[range.prim.size.hint]`: `auto(reserve_hint(t))` is a valid expression
+  template <__freestanding_reserve_hint _Tp>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const
+      noexcept(noexcept(auto(reserve_hint(__t)))) {
+    return auto(reserve_hint(__t));
+  }
+};
+} // namespace __reserve_hint
+
+inline namespace __cpo {
+inline constexpr auto reserve_hint = __reserve_hint::__fn{};
+} // namespace __cpo
+} // namespace ranges
+
+#  endif // _LIBCPP_STD_VER >= 26
+
 #endif // _LIBCPP_STD_VER >= 20
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__ranges/stride_view.h b/libcxx/include/__ranges/stride_view.h
index 780bb25743c15..d4b7cce06eb91 100644
--- a/libcxx/include/__ranges/stride_view.h
+++ b/libcxx/include/__ranges/stride_view.h
@@ -30,6 +30,7 @@
 #include <__ranges/concepts.h>
 #include <__ranges/enable_borrowed_range.h>
 #include <__ranges/range_adaptor.h>
+#include <__ranges/size.h>
 #include <__ranges/view_interface.h>
 #include <__type_traits/make_unsigned.h>
 
@@ -129,6 +130,24 @@ class stride_view : public view_interface<stride_view<_View>> {
   {
     return std::__to_unsigned_like(ranges::__div_ceil(ranges::distance(__base_), __stride_));
   }
+
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires approximately_sized_range<_View>
+  {
+    auto __s = static_cast<range_difference_t<decltype((__base_))>>(ranges::reserve_hint(__base_));
+    return __to_unsigned_like(__div_ceil(__s, __stride_));
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const
+    requires approximately_sized_range<const _View>
+  {
+    auto __s = static_cast<range_difference_t<decltype((__base_))>>(ranges::reserve_hint(__base_));
+    return __to_unsigned_like(__div_ceil(__s, __stride_));
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
 }; // class stride_view
 
 template <class _Range>
diff --git a/libcxx/include/__ranges/take_view.h b/libcxx/include/__ranges/take_view.h
index 999f686537f2c..f97a88ccf9297 100644
--- a/libcxx/include/__ranges/take_view.h
+++ b/libcxx/include/__ranges/take_view.h
@@ -155,6 +155,26 @@ class take_view : public view_interface<take_view<_View>> {
     auto __n = ranges::size(__base_);
     return ranges::min(__n, static_cast<decltype(__n)>(__count_));
   }
+
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() {
+    if constexpr (approximately_sized_range<_View>) {
+      auto __n = static_cast<range_difference_t<_View>>(ranges::reserve_hint(__base_));
+      return __to_unsigned_like(ranges::min(__n, __count_));
+    }
+    return __to_unsigned_like(__count_);
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint() const {
+    if constexpr (approximately_sized_range<const _View>) {
+      auto __n = static_cast<range_difference_t<const _View>>(ranges::reserve_hint(__base_));
+      return __to_unsigned_like(ranges::min(__n, __count_));
+    }
+    return __to_unsigned_like(__count_);
+  }
+
+#  endif //_LIBCPP_STD_VER >= 26
 };
 
 template <view _View>
diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h
index 1484be006e841..c26b7ea362a8d 100644
--- a/libcxx/include/__ranges/transform_view.h
+++ b/libcxx/include/__ranges/transform_view.h
@@ -139,6 +139,22 @@ class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS transform_view : public view_interfac
   {
     return ranges::size(__base_);
   }
+
+#  if _LIBCPP_STD_VER >= 26
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto reserve_hint()
+    requires approximately_sized_range<_View>
+  {
+    return ranges::reserve_hint(__base_);
+  }
...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/206385


More information about the libcxx-commits mailing list