[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