[libcxx-commits] [libcxx] [libc++] Implement P3508R0: Wording for "constexpr for specialized memory algorithms" (PR #197313)
William Tran-Viet via libcxx-commits
libcxx-commits at lists.llvm.org
Sun May 24 13:08:29 PDT 2026
https://github.com/smallp-o-p updated https://github.com/llvm/llvm-project/pull/197313
>From 69ac5b66dcf6336b2e0317536ef104afa68dc1c5 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 12 May 2026 17:14:34 -0400
Subject: [PATCH 01/18] Implement P3508R0
---
libcxx/docs/FeatureTestMacroTable.rst | 3 +-
libcxx/docs/Status/Cxx2cPapers.csv | 2 +-
.../ranges_uninitialized_algorithms.h | 42 ++++++++++-------
.../__memory/uninitialized_algorithms.h | 47 +++++++++++--------
4 files changed, 54 insertions(+), 40 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index ae48eaed1f46b..0d455beacd6df 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -138,7 +138,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_parallel_algorithm`` *unimplemented*
---------------------------------------------------------- -----------------
- ``__cpp_lib_raw_memory_algorithms`` ``201606L``
+ ``__cpp_lib_raw_memory_algorithms`` ``202406L``
---------------------------------------------------------- -----------------
``__cpp_lib_sample`` ``201603L``
---------------------------------------------------------- -----------------
@@ -542,4 +542,3 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_variant`` ``202306L``
========================================================== =================
-
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index eb15fac940f5c..8f8ca6825c246 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -87,7 +87,7 @@
"`P3396R1 <https://wg21.link/P3396R1>`__","``std::execution`` wording fixes","2024-11 (Wrocław)","","","`#118376 <https://github.com/llvm/llvm-project/issues/118376>`__",""
"`P2835R7 <https://wg21.link/P2835R7>`__","Expose ``std::atomic_ref``'s object address","2024-11 (Wrocław)","|Complete|","22","`#118377 <https://github.com/llvm/llvm-project/issues/118377>`__",""
"`P3323R1 <https://wg21.link/P3323R1>`__","cv-qualified types in ``atomic`` and ``atomic_ref``","2024-11 (Wrocław)","","","`#118378 <https://github.com/llvm/llvm-project/issues/118378>`__",""
-"`P3508R0 <https://wg21.link/P3508R0>`__","Wording for ""constexpr for specialized memory algorithms""","2024-11 (Wrocław)","","","`#118379 <https://github.com/llvm/llvm-project/issues/118379>`__",""
+"`P3508R0 <https://wg21.link/P3508R0>`__","Wording for ""constexpr for specialized memory algorithms""","2024-11 (Wrocław)","|Complete|","23","`#118379 <https://github.com/llvm/llvm-project/issues/118379>`__",""
"`P3369R0 <https://wg21.link/P3369R0>`__","constexpr for ``uninitialized_default_construct``","2024-11 (Wrocław)","","","`#118380 <https://github.com/llvm/llvm-project/issues/118380>`__",""
"`P3370R1 <https://wg21.link/P3370R1>`__","Add new library headers from C23","2024-11 (Wrocław)","","","`#118381 <https://github.com/llvm/llvm-project/issues/118381>`__",""
"`P3309R3 <https://wg21.link/P3309R3>`__","constexpr ``atomic`` and ``atomic_ref``","2024-11 (Wrocław)","","","`#118382 <https://github.com/llvm/llvm-project/issues/118382>`__",""
diff --git a/libcxx/include/__memory/ranges_uninitialized_algorithms.h b/libcxx/include/__memory/ranges_uninitialized_algorithms.h
index 57a7a4616826e..83e33527f35d3 100644
--- a/libcxx/include/__memory/ranges_uninitialized_algorithms.h
+++ b/libcxx/include/__memory/ranges_uninitialized_algorithms.h
@@ -44,14 +44,16 @@ namespace ranges {
struct __uninitialized_default_construct {
template <__nothrow_forward_iterator _ForwardIterator, __nothrow_sentinel_for<_ForwardIterator> _Sentinel>
requires default_initializable<iter_value_t<_ForwardIterator>>
- _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last) const {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
+ operator()(_ForwardIterator __first, _Sentinel __last) const {
using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>;
return std::__uninitialized_default_construct<_ValueType>(std::move(__first), std::move(__last));
}
template <__nothrow_forward_range _ForwardRange>
requires default_initializable<range_value_t<_ForwardRange>>
- _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range) const {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_iterator_t<_ForwardRange>
+ operator()(_ForwardRange&& __range) const {
return (*this)(ranges::begin(__range), ranges::end(__range));
}
};
@@ -65,7 +67,7 @@ inline constexpr auto uninitialized_default_construct = __uninitialized_default_
struct __uninitialized_default_construct_n {
template <__nothrow_forward_iterator _ForwardIterator>
requires default_initializable<iter_value_t<_ForwardIterator>>
- _LIBCPP_HIDE_FROM_ABI _ForwardIterator
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
operator()(_ForwardIterator __first, iter_difference_t<_ForwardIterator> __n) const {
using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>;
return std::__uninitialized_default_construct_n<_ValueType>(std::move(__first), __n);
@@ -81,14 +83,16 @@ inline constexpr auto uninitialized_default_construct_n = __uninitialized_defaul
struct __uninitialized_value_construct {
template <__nothrow_forward_iterator _ForwardIterator, __nothrow_sentinel_for<_ForwardIterator> _Sentinel>
requires default_initializable<iter_value_t<_ForwardIterator>>
- _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last) const {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
+ operator()(_ForwardIterator __first, _Sentinel __last) const {
using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>;
return std::__uninitialized_value_construct<_ValueType>(std::move(__first), std::move(__last));
}
template <__nothrow_forward_range _ForwardRange>
requires default_initializable<range_value_t<_ForwardRange>>
- _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range) const {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_iterator_t<_ForwardRange>
+ operator()(_ForwardRange&& __range) const {
return (*this)(ranges::begin(__range), ranges::end(__range));
}
};
@@ -102,7 +106,7 @@ inline constexpr auto uninitialized_value_construct = __uninitialized_value_cons
struct __uninitialized_value_construct_n {
template <__nothrow_forward_iterator _ForwardIterator>
requires default_initializable<iter_value_t<_ForwardIterator>>
- _LIBCPP_HIDE_FROM_ABI _ForwardIterator
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
operator()(_ForwardIterator __first, iter_difference_t<_ForwardIterator> __n) const {
using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>;
return std::__uninitialized_value_construct_n<_ValueType>(std::move(__first), __n);
@@ -118,14 +122,16 @@ inline constexpr auto uninitialized_value_construct_n = __uninitialized_value_co
struct __uninitialized_fill {
template <__nothrow_forward_iterator _ForwardIterator, __nothrow_sentinel_for<_ForwardIterator> _Sentinel, class _Tp>
requires constructible_from<iter_value_t<_ForwardIterator>, const _Tp&>
- _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) const {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
+ operator()(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) const {
using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>;
return std::__uninitialized_fill<_ValueType>(std::move(__first), std::move(__last), __x);
}
template <__nothrow_forward_range _ForwardRange, class _Tp>
requires constructible_from<range_value_t<_ForwardRange>, const _Tp&>
- _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range, const _Tp& __x) const {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_iterator_t<_ForwardRange>
+ operator()(_ForwardRange&& __range, const _Tp& __x) const {
return (*this)(ranges::begin(__range), ranges::end(__range), __x);
}
};
@@ -139,7 +145,7 @@ inline constexpr auto uninitialized_fill = __uninitialized_fill{};
struct __uninitialized_fill_n {
template <__nothrow_forward_iterator _ForwardIterator, class _Tp>
requires constructible_from<iter_value_t<_ForwardIterator>, const _Tp&>
- _LIBCPP_HIDE_FROM_ABI _ForwardIterator
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
operator()(_ForwardIterator __first, iter_difference_t<_ForwardIterator> __n, const _Tp& __x) const {
using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>;
return std::__uninitialized_fill_n<_ValueType>(std::move(__first), __n, __x);
@@ -161,7 +167,7 @@ struct __uninitialized_copy {
__nothrow_forward_iterator _OutputIterator,
__nothrow_sentinel_for<_OutputIterator> _Sentinel2>
requires constructible_from<iter_value_t<_OutputIterator>, iter_reference_t<_InputIterator>>
- _LIBCPP_HIDE_FROM_ABI uninitialized_copy_result<_InputIterator, _OutputIterator>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 uninitialized_copy_result<_InputIterator, _OutputIterator>
operator()(_InputIterator __ifirst, _Sentinel1 __ilast, _OutputIterator __ofirst, _Sentinel2 __olast) const {
using _ValueType = remove_reference_t<iter_reference_t<_OutputIterator>>;
@@ -173,8 +179,9 @@ struct __uninitialized_copy {
template <input_range _InputRange, __nothrow_forward_range _OutputRange>
requires constructible_from<range_value_t<_OutputRange>, range_reference_t<_InputRange>>
- _LIBCPP_HIDE_FROM_ABI uninitialized_copy_result<borrowed_iterator_t<_InputRange>, borrowed_iterator_t<_OutputRange>>
- operator()(_InputRange&& __in_range, _OutputRange&& __out_range) const {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
+ uninitialized_copy_result<borrowed_iterator_t<_InputRange>, borrowed_iterator_t<_OutputRange>>
+ operator()(_InputRange&& __in_range, _OutputRange&& __out_range) const {
return (*this)(
ranges::begin(__in_range), ranges::end(__in_range), ranges::begin(__out_range), ranges::end(__out_range));
}
@@ -194,7 +201,7 @@ struct __uninitialized_copy_n {
__nothrow_forward_iterator _OutputIterator,
__nothrow_sentinel_for<_OutputIterator> _Sentinel>
requires constructible_from<iter_value_t<_OutputIterator>, iter_reference_t<_InputIterator>>
- _LIBCPP_HIDE_FROM_ABI uninitialized_copy_n_result<_InputIterator, _OutputIterator>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 uninitialized_copy_n_result<_InputIterator, _OutputIterator>
operator()(_InputIterator __ifirst,
iter_difference_t<_InputIterator> __n,
_OutputIterator __ofirst,
@@ -222,7 +229,7 @@ struct __uninitialized_move {
__nothrow_forward_iterator _OutputIterator,
__nothrow_sentinel_for<_OutputIterator> _Sentinel2>
requires constructible_from<iter_value_t<_OutputIterator>, iter_rvalue_reference_t<_InputIterator>>
- _LIBCPP_HIDE_FROM_ABI uninitialized_move_result<_InputIterator, _OutputIterator>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 uninitialized_move_result<_InputIterator, _OutputIterator>
operator()(_InputIterator __ifirst, _Sentinel1 __ilast, _OutputIterator __ofirst, _Sentinel2 __olast) const {
using _ValueType = remove_reference_t<iter_reference_t<_OutputIterator>>;
auto __iter_move = [](auto&& __iter) -> decltype(auto) { return ranges::iter_move(__iter); };
@@ -234,8 +241,9 @@ struct __uninitialized_move {
template <input_range _InputRange, __nothrow_forward_range _OutputRange>
requires constructible_from<range_value_t<_OutputRange>, range_rvalue_reference_t<_InputRange>>
- _LIBCPP_HIDE_FROM_ABI uninitialized_move_result<borrowed_iterator_t<_InputRange>, borrowed_iterator_t<_OutputRange>>
- operator()(_InputRange&& __in_range, _OutputRange&& __out_range) const {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
+ uninitialized_move_result<borrowed_iterator_t<_InputRange>, borrowed_iterator_t<_OutputRange>>
+ operator()(_InputRange&& __in_range, _OutputRange&& __out_range) const {
return (*this)(
ranges::begin(__in_range), ranges::end(__in_range), ranges::begin(__out_range), ranges::end(__out_range));
}
@@ -255,7 +263,7 @@ struct __uninitialized_move_n {
__nothrow_forward_iterator _OutputIterator,
__nothrow_sentinel_for<_OutputIterator> _Sentinel>
requires constructible_from<iter_value_t<_OutputIterator>, iter_rvalue_reference_t<_InputIterator>>
- _LIBCPP_HIDE_FROM_ABI uninitialized_move_n_result<_InputIterator, _OutputIterator>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 uninitialized_move_n_result<_InputIterator, _OutputIterator>
operator()(_InputIterator __ifirst,
iter_difference_t<_InputIterator> __n,
_OutputIterator __ofirst,
diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h
index 9182db4b412e3..eded04eb06be0 100644
--- a/libcxx/include/__memory/uninitialized_algorithms.h
+++ b/libcxx/include/__memory/uninitialized_algorithms.h
@@ -57,7 +57,7 @@ struct __always_false {
// uninitialized_copy
template <class _ValueType, class _InputIterator, class _Sentinel1, class _ForwardIterator, class _EndPredicate>
-inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_copy(
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<_InputIterator, _ForwardIterator> __uninitialized_copy(
_InputIterator __ifirst, _Sentinel1 __ilast, _ForwardIterator __ofirst, _EndPredicate __stop_copying) {
_ForwardIterator __idx = __ofirst;
auto __guard = std::__make_exception_guard([&] { std::__destroy(__ofirst, __idx); });
@@ -69,7 +69,7 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitiali
}
template <class _InputIterator, class _ForwardIterator>
-_LIBCPP_HIDE_FROM_ABI _ForwardIterator
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
uninitialized_copy(_InputIterator __ifirst, _InputIterator __ilast, _ForwardIterator __ofirst) {
typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
auto __result = std::__uninitialized_copy<_ValueType>(
@@ -80,7 +80,7 @@ uninitialized_copy(_InputIterator __ifirst, _InputIterator __ilast, _ForwardIter
// uninitialized_copy_n
template <class _ValueType, class _InputIterator, class _Size, class _ForwardIterator, class _EndPredicate>
-inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator>
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<_InputIterator, _ForwardIterator>
__uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _EndPredicate __stop_copying) {
_ForwardIterator __idx = __ofirst;
auto __guard = std::__make_exception_guard([&] { std::__destroy(__ofirst, __idx); });
@@ -92,7 +92,7 @@ __uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __of
}
template <class _InputIterator, class _Size, class _ForwardIterator>
-inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst) {
typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
auto __result =
@@ -103,7 +103,7 @@ uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofir
// uninitialized_fill
template <class _ValueType, class _ForwardIterator, class _Sentinel, class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
__uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) {
_ForwardIterator __idx = __first;
auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
@@ -115,7 +115,7 @@ __uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x)
}
template <class _ForwardIterator, class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI void
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __x) {
typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
(void)std::__uninitialized_fill<_ValueType>(__first, __last, __x);
@@ -124,7 +124,7 @@ uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp&
// uninitialized_fill_n
template <class _ValueType, class _ForwardIterator, class _Size, class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
__uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) {
_ForwardIterator __idx = __first;
auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
@@ -136,7 +136,7 @@ __uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) {
}
template <class _ForwardIterator, class _Size, class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) {
typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
return std::__uninitialized_fill_n<_ValueType>(__first, __n, __x);
@@ -147,7 +147,7 @@ uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) {
// uninitialized_default_construct
template <class _ValueType, class _ForwardIterator, class _Sentinel>
-inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
__uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) {
auto __idx = __first;
auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
@@ -159,7 +159,8 @@ __uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) {
}
template <class _ForwardIterator>
-inline _LIBCPP_HIDE_FROM_ABI void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
+uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) {
using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
(void)std::__uninitialized_default_construct<_ValueType>(std::move(__first), std::move(__last));
}
@@ -167,7 +168,8 @@ inline _LIBCPP_HIDE_FROM_ABI void uninitialized_default_construct(_ForwardIterat
// uninitialized_default_construct_n
template <class _ValueType, class _ForwardIterator, class _Size>
-inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
+__uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
auto __idx = __first;
auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
for (; __n > 0; ++__idx, (void)--__n)
@@ -178,7 +180,8 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct_
}
template <class _ForwardIterator, class _Size>
-inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
+uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
return std::__uninitialized_default_construct_n<_ValueType>(std::move(__first), __n);
}
@@ -186,7 +189,7 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_default_construct_n(
// uninitialized_value_construct
template <class _ValueType, class _ForwardIterator, class _Sentinel>
-inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
__uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) {
auto __idx = __first;
auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
@@ -198,7 +201,8 @@ __uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) {
}
template <class _ForwardIterator>
-inline _LIBCPP_HIDE_FROM_ABI void uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
+uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) {
using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
(void)std::__uninitialized_value_construct<_ValueType>(std::move(__first), std::move(__last));
}
@@ -206,7 +210,8 @@ inline _LIBCPP_HIDE_FROM_ABI void uninitialized_value_construct(_ForwardIterator
// uninitialized_value_construct_n
template <class _ValueType, class _ForwardIterator, class _Size>
-inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
+__uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) {
auto __idx = __first;
auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
for (; __n > 0; ++__idx, (void)--__n)
@@ -217,7 +222,8 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct_n(
}
template <class _ForwardIterator, class _Size>
-inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
+uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) {
using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
return std::__uninitialized_value_construct_n<_ValueType>(std::move(__first), __n);
}
@@ -230,7 +236,7 @@ template <class _ValueType,
class _ForwardIterator,
class _EndPredicate,
class _IterMove>
-inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move(
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<_InputIterator, _ForwardIterator> __uninitialized_move(
_InputIterator __ifirst,
_Sentinel1 __ilast,
_ForwardIterator __ofirst,
@@ -247,7 +253,7 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitiali
}
template <class _InputIterator, class _ForwardIterator>
-inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
uninitialized_move(_InputIterator __ifirst, _InputIterator __ilast, _ForwardIterator __ofirst) {
using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
auto __iter_move = [](auto&& __iter) -> decltype(auto) { return std::move(*__iter); };
@@ -265,7 +271,8 @@ template <class _ValueType,
class _ForwardIterator,
class _EndPredicate,
class _IterMove>
-inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move_n(
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<_InputIterator, _ForwardIterator>
+__uninitialized_move_n(
_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _EndPredicate __stop_moving, _IterMove __iter_move) {
auto __idx = __ofirst;
auto __guard = std::__make_exception_guard([&] { std::__destroy(__ofirst, __idx); });
@@ -277,7 +284,7 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitiali
}
template <class _InputIterator, class _Size, class _ForwardIterator>
-inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator>
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<_InputIterator, _ForwardIterator>
uninitialized_move_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst) {
using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
auto __iter_move = [](auto&& __iter) -> decltype(auto) { return std::move(*__iter); };
>From 05f35e36d53ceaf30f51bf468f1d13b0bf57a0b7 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 12 May 2026 17:43:22 -0400
Subject: [PATCH 02/18] Add constexpr tests
---
.../ranges_uninitialized_copy.pass.cpp | 55 ++++++++++++++++++
.../ranges_uninitialized_copy_n.pass.cpp | 40 +++++++++++++
.../uninitialized_copy.pass.cpp | 27 +++++++++
.../uninitialized_copy_n.pass.cpp | 29 +++++++++-
.../ranges_uninitialized_fill_n.pass.cpp | 23 ++++++++
.../uninitialized_fill_n.pass.cpp | 27 +++++++++
.../ranges_uninitialized_fill.pass.cpp | 39 +++++++++++++
.../uninitialized_fill.pass.cpp | 26 +++++++++
.../ranges_uninitialized_move.pass.cpp | 57 +++++++++++++++++++
.../ranges_uninitialized_move_n.pass.cpp | 41 +++++++++++++
.../uninitialized_move.pass.cpp | 29 +++++++++-
.../uninitialized_move_n.pass.cpp | 28 +++++++++
12 files changed, 419 insertions(+), 2 deletions(-)
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/ranges_uninitialized_copy.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/ranges_uninitialized_copy.pass.cpp
index 52ba70b009bab..51cef5033a307 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/ranges_uninitialized_copy.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/ranges_uninitialized_copy.pass.cpp
@@ -28,6 +28,7 @@
#include "../buffer.h"
#include "../counted.h"
#include "../overload_compare_iterator.h"
+#include "copy_move_types.h"
#include "test_macros.h"
#include "test_iterators.h"
@@ -42,6 +43,55 @@ struct NotConvertibleFromInt {};
static_assert(!std::is_invocable_v<decltype(std::ranges::uninitialized_copy), int*, int*, NotConvertibleFromInt*,
NotConvertibleFromInt*>);
+TEST_CONSTEXPR_CXX26 bool test() {
+ constexpr int n = 3;
+ const ConstCopy in[n] = {ConstCopy(1), ConstCopy(2), ConstCopy(3)};
+ std::allocator<ConstCopy> alloc;
+
+ // (iter, sentinel) overload.
+ {
+ ConstCopy* out = alloc.allocate(n);
+ auto result = std::ranges::uninitialized_copy(in, in + n, out, out + n);
+ assert(result.in == in + n);
+ assert(result.out == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == in[i].val);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ // (range) overload.
+ {
+ ConstCopy* out = alloc.allocate(n);
+ auto out_range = std::ranges::subrange(out, out + n);
+ auto result = std::ranges::uninitialized_copy(in, out_range);
+ assert(result.in == in + n);
+ assert(result.out == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == in[i].val);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ // Destination range is shorter than the source range.
+ {
+ constexpr int m = 2;
+ ConstCopy* out = alloc.allocate(m);
+ auto result = std::ranges::uninitialized_copy(in, in + n, out, out + m);
+ assert(result.in == in + m);
+ assert(result.out == out + m);
+ for (int i = 0; i != m; ++i)
+ assert(out[i].val == in[i].val);
+
+ std::destroy(out, out + m);
+ alloc.deallocate(out, m);
+ }
+
+ return true;
+}
+
int main(int, char**) {
// An empty range -- no default constructors should be invoked.
{
@@ -395,5 +445,10 @@ int main(int, char**) {
}
}
+ test();
+#if TEST_STD_VER >= 26
+ static_assert(test());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/ranges_uninitialized_copy_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/ranges_uninitialized_copy_n.pass.cpp
index 84fba1aa79293..afb565c258715 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/ranges_uninitialized_copy_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/ranges_uninitialized_copy_n.pass.cpp
@@ -25,6 +25,7 @@
#include "../buffer.h"
#include "../counted.h"
#include "../overload_compare_iterator.h"
+#include "copy_move_types.h"
#include "test_macros.h"
#include "test_iterators.h"
@@ -39,6 +40,40 @@ struct NotConvertibleFromInt {};
static_assert(!std::is_invocable_v<decltype(std::ranges::uninitialized_copy_n), int*, std::size_t, NotConvertibleFromInt*,
NotConvertibleFromInt*>);
+TEST_CONSTEXPR_CXX26 bool test() {
+ constexpr int n = 3;
+ const ConstCopy in[n] = {ConstCopy(1), ConstCopy(2), ConstCopy(3)};
+ std::allocator<ConstCopy> alloc;
+
+ {
+ ConstCopy* out = alloc.allocate(n);
+ auto result = std::ranges::uninitialized_copy_n(in, n, out, out + n);
+ assert(result.in == in + n);
+ assert(result.out == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == in[i].val);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ // Destination range is shorter than the source range.
+ {
+ constexpr int m = 2;
+ ConstCopy* out = alloc.allocate(m);
+ auto result = std::ranges::uninitialized_copy_n(in, n, out, out + m);
+ assert(result.in == in + m);
+ assert(result.out == out + m);
+ for (int i = 0; i != m; ++i)
+ assert(out[i].val == in[i].val);
+
+ std::destroy(out, out + m);
+ alloc.deallocate(out, m);
+ }
+
+ return true;
+}
+
int main(int, char**) {
// An empty range -- no default constructors should be invoked.
{
@@ -177,5 +212,10 @@ int main(int, char**) {
}
}
+ test();
+#if TEST_STD_VER >= 26
+ static_assert(test());
+#endif // TEST_STD_VER >= 26
+
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp
index dddc550e0ef12..4a25d4c1025d5 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp
@@ -17,6 +17,9 @@
#include <cassert>
#include "test_macros.h"
+#if TEST_STD_VER >= 26
+# include "copy_move_types.h"
+#endif
#include "../overload_compare_iterator.h"
struct B
@@ -48,6 +51,25 @@ struct Nasty
int Nasty::counter_ = 0;
+#if TEST_STD_VER >= 26
+TEST_CONSTEXPR_CXX26 bool test() {
+ const int n = 3;
+ const ConstCopy in[n] = {ConstCopy(1), ConstCopy(2), ConstCopy(3)};
+ std::allocator<ConstCopy> alloc;
+ ConstCopy* out = alloc.allocate(n);
+
+ ConstCopy* result = std::uninitialized_copy(in, in + n, out);
+ assert(result == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == in[i].val);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+
+ return true;
+}
+#endif // TEST_STD_VER >= 26
+
int main(int, char**)
{
{
@@ -115,5 +137,10 @@ int main(int, char**)
}
}
+#if TEST_STD_VER >= 26
+ test();
+ static_assert(test());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp
index ddaf02c184bd4..e725c42a14733 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp
@@ -17,6 +17,9 @@
#include <cassert>
#include "test_macros.h"
+#if TEST_STD_VER >= 26
+# include "copy_move_types.h"
+#endif
#include "../overload_compare_iterator.h"
struct B
@@ -48,6 +51,25 @@ struct Nasty
int Nasty::counter_ = 0;
+#if TEST_STD_VER >= 26
+TEST_CONSTEXPR_CXX26 bool test() {
+ const int n = 3;
+ const ConstCopy in[n] = {ConstCopy(1), ConstCopy(2), ConstCopy(3)};
+ std::allocator<ConstCopy> alloc;
+ ConstCopy* out = alloc.allocate(n);
+
+ ConstCopy* result = std::uninitialized_copy_n(in, n, out);
+ assert(result == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == in[i].val);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+
+ return true;
+}
+#endif // TEST_STD_VER >= 26
+
int main(int, char**)
{
{
@@ -115,5 +137,10 @@ int main(int, char**)
}
}
- return 0;
+#if TEST_STD_VER >= 26
+ test();
+ static_assert(test());
+#endif // TEST_STD_VER >= 26
+
+ return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/ranges_uninitialized_fill_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/ranges_uninitialized_fill_n.pass.cpp
index 0b35c1114d87c..4420cde5587e8 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/ranges_uninitialized_fill_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/ranges_uninitialized_fill_n.pass.cpp
@@ -23,6 +23,7 @@
#include "../buffer.h"
#include "../counted.h"
+#include "copy_move_types.h"
#include "test_macros.h"
#include "test_iterators.h"
@@ -35,6 +36,23 @@ LIBCPP_STATIC_ASSERT(std::is_class_v<decltype(std::ranges::uninitialized_fill_n)
struct NotConvertibleFromInt {};
static_assert(!std::is_invocable_v<decltype(std::ranges::uninitialized_fill_n), NotConvertibleFromInt*, std::size_t, int>);
+TEST_CONSTEXPR_CXX26 bool test() {
+ constexpr int n = 3;
+ ConstCopy value(42);
+ std::allocator<ConstCopy> alloc;
+
+ ConstCopy* out = alloc.allocate(n);
+ auto result = std::ranges::uninitialized_fill_n(out, n, value);
+ assert(result == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == value.val);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+
+ return true;
+}
+
int main(int, char**) {
constexpr int value = 42;
Counted x(value);
@@ -101,5 +119,10 @@ int main(int, char**) {
}
#endif // TEST_HAS_NO_EXCEPTIONS
+ test();
+#if TEST_STD_VER >= 26
+ static_assert(test());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp
index 8b46f1ba67aa3..09fd8a78332f2 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp
@@ -16,6 +16,9 @@
#include <cassert>
#include "test_macros.h"
+#if TEST_STD_VER >= 26
+# include "copy_move_types.h"
+#endif
struct B
{
@@ -46,6 +49,25 @@ struct Nasty
int Nasty::counter_ = 0;
+#if TEST_STD_VER >= 26
+TEST_CONSTEXPR_CXX26 bool test() {
+ const int n = 3;
+ ConstCopy value(42);
+ std::allocator<ConstCopy> alloc;
+ ConstCopy* out = alloc.allocate(n);
+
+ ConstCopy* result = std::uninitialized_fill_n(out, n, value);
+ assert(result == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == value.val);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+
+ return true;
+}
+#endif // TEST_STD_VER >= 26
+
int main(int, char**)
{
{
@@ -85,5 +107,10 @@ int main(int, char**)
}
+#if TEST_STD_VER >= 26
+ test();
+ static_assert(test());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/ranges_uninitialized_fill.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/ranges_uninitialized_fill.pass.cpp
index 6f75fc13a1c39..3cbdf58cc2281 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/ranges_uninitialized_fill.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/ranges_uninitialized_fill.pass.cpp
@@ -27,6 +27,7 @@
#include "../buffer.h"
#include "../counted.h"
+#include "copy_move_types.h"
#include "test_macros.h"
#include "test_iterators.h"
@@ -40,6 +41,39 @@ struct NotConvertibleFromInt {};
static_assert(!std::is_invocable_v<decltype(std::ranges::uninitialized_fill), NotConvertibleFromInt*,
NotConvertibleFromInt*, int>);
+TEST_CONSTEXPR_CXX26 bool test() {
+ constexpr int n = 3;
+ ConstCopy value(42);
+ std::allocator<ConstCopy> alloc;
+
+ // (iter, sentinel) overload.
+ {
+ ConstCopy* out = alloc.allocate(n);
+ auto result = std::ranges::uninitialized_fill(out, out + n, value);
+ assert(result == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == value.val);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ // (range) overload.
+ {
+ ConstCopy* out = alloc.allocate(n);
+ auto out_range = std::ranges::subrange(out, out + n);
+ auto result = std::ranges::uninitialized_fill(out_range, value);
+ assert(result == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == value.val);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ return true;
+}
+
int main(int, char**) {
constexpr int value = 42;
Counted x(value);
@@ -198,5 +232,10 @@ int main(int, char**) {
}
#endif // TEST_HAS_NO_EXCEPTIONS
+ test();
+#if TEST_STD_VER >= 26
+ static_assert(test());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp
index fd6576d79ad1a..5e5633b0106d6 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp
@@ -17,6 +17,9 @@
#include <cassert>
#include "test_macros.h"
+#if TEST_STD_VER >= 26
+# include "copy_move_types.h"
+#endif
struct B
{
@@ -47,6 +50,24 @@ struct Nasty
int Nasty::counter_ = 0;
+#if TEST_STD_VER >= 26
+TEST_CONSTEXPR_CXX26 bool test() {
+ int n = 3;
+ ConstCopy value(42);
+ std::allocator<ConstCopy> alloc;
+ ConstCopy* out = alloc.allocate(n);
+
+ std::uninitialized_fill(out, out + n, value);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == value.val);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+
+ return true;
+}
+#endif // TEST_STD_VER >= 26
+
int main(int, char**)
{
{
@@ -82,5 +103,10 @@ int main(int, char**)
assert(bp[i].i_ == 23);
}
+#if TEST_STD_VER >= 26
+ test();
+ static_assert(test());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move.pass.cpp
index c6b38b4fea864..d37d49918ac05 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move.pass.cpp
@@ -29,6 +29,7 @@
#include "../counted.h"
#include "../overload_compare_iterator.h"
#include "MoveOnly.h"
+#include "copy_move_types.h"
#include "test_macros.h"
#include "test_iterators.h"
@@ -43,6 +44,57 @@ struct NotConvertibleFromInt {};
static_assert(!std::is_invocable_v<decltype(std::ranges::uninitialized_move), int*, int*, NotConvertibleFromInt*,
NotConvertibleFromInt*>);
+TEST_CONSTEXPR_CXX26 bool test() {
+ constexpr int n = 3;
+ std::allocator<MutableMove> alloc;
+
+ // (iter, sentinel) overload.
+ {
+ MutableMove in[n] = {MutableMove(1), MutableMove(2), MutableMove(3)};
+ MutableMove* out = alloc.allocate(n);
+ auto result = std::ranges::uninitialized_move(in, in + n, out, out + n);
+ assert(result.in == in + n);
+ assert(result.out == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == i + 1);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ // (range) overload.
+ {
+ MutableMove in[n] = {MutableMove(1), MutableMove(2), MutableMove(3)};
+ MutableMove* out = alloc.allocate(n);
+ auto out_range = std::ranges::subrange(out, out + n);
+ auto result = std::ranges::uninitialized_move(in, out_range);
+ assert(result.in == in + n);
+ assert(result.out == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == i + 1);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ // Destination range is shorter than the source range.
+ {
+ constexpr int m = 2;
+ MutableMove in[n] = {MutableMove(1), MutableMove(2), MutableMove(3)};
+ MutableMove* out = alloc.allocate(m);
+ auto result = std::ranges::uninitialized_move(in, in + n, out, out + m);
+ assert(result.in == in + m);
+ assert(result.out == out + m);
+ for (int i = 0; i != m; ++i)
+ assert(out[i].val == i + 1);
+
+ std::destroy(out, out + m);
+ alloc.deallocate(out, m);
+ }
+
+ return true;
+}
+
int main(int, char**) {
// An empty range -- no default constructors should be invoked.
{
@@ -434,5 +486,10 @@ int main(int, char**) {
}
}
+ test();
+#if TEST_STD_VER >= 26
+ static_assert(test());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move_n.pass.cpp
index cac2acc5932b3..5168a7aa7b733 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move_n.pass.cpp
@@ -26,6 +26,7 @@
#include "../counted.h"
#include "../overload_compare_iterator.h"
#include "MoveOnly.h"
+#include "copy_move_types.h"
#include "test_iterators.h"
#include "test_macros.h"
@@ -40,6 +41,41 @@ struct NotConvertibleFromInt {};
static_assert(!std::is_invocable_v<decltype(std::ranges::uninitialized_move_n), int*, std::size_t, NotConvertibleFromInt*,
NotConvertibleFromInt*>);
+TEST_CONSTEXPR_CXX26 bool test() {
+ constexpr int n = 3;
+ std::allocator<MutableMove> alloc;
+
+ {
+ MutableMove in[n] = {MutableMove(1), MutableMove(2), MutableMove(3)};
+ MutableMove* out = alloc.allocate(n);
+ auto result = std::ranges::uninitialized_move_n(in, n, out, out + n);
+ assert(result.in == in + n);
+ assert(result.out == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i].val == i + 1);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ // Destination range is shorter than the source range.
+ {
+ constexpr int m = 2;
+ MutableMove in[n] = {MutableMove(1), MutableMove(2), MutableMove(3)};
+ MutableMove* out = alloc.allocate(m);
+ auto result = std::ranges::uninitialized_move_n(in, n, out, out + m);
+ assert(result.in == in + m);
+ assert(result.out == out + m);
+ for (int i = 0; i != m; ++i)
+ assert(out[i].val == i + 1);
+
+ std::destroy(out, out + m);
+ alloc.deallocate(out, m);
+ }
+
+ return true;
+}
+
int main(int, char**) {
// An empty range -- no default constructors should be invoked.
{
@@ -207,5 +243,10 @@ int main(int, char**) {
}
}
+ test();
+#if TEST_STD_VER >= 26
+ static_assert(test());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp
index f77cbea19bd4d..c0716a69a24d7 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp
@@ -18,6 +18,9 @@
#include <cassert>
#include "test_macros.h"
+#if TEST_STD_VER >= 26
+# include "copy_move_types.h"
+#endif
#include "test_iterators.h"
#include "../overload_compare_iterator.h"
@@ -55,6 +58,25 @@ int ThrowsCounted::count = 0;
int ThrowsCounted::constructed = 0;
int ThrowsCounted::throw_after = 0;
+#if TEST_STD_VER >= 26
+TEST_CONSTEXPR_CXX26 bool test() {
+ const int N = 3;
+ MutableMove in[N] = {MutableMove(1), MutableMove(2), MutableMove(3)};
+ std::allocator<MutableMove> alloc;
+ MutableMove* out = alloc.allocate(N);
+
+ MutableMove* result = std::uninitialized_move(in, in + N, out);
+ assert(result == out + N);
+ for (int i = 0; i != N; ++i)
+ assert(out[i].val == i + 1);
+
+ std::destroy(out, out + N);
+ alloc.deallocate(out, N);
+
+ return true;
+}
+#endif // TEST_STD_VER >= 26
+
void test_ctor_throws()
{
#ifndef TEST_HAS_NO_EXCEPTIONS
@@ -141,5 +163,10 @@ int main(int, char**) {
}
}
- return 0;
+#if TEST_STD_VER >= 26
+ test();
+ static_assert(test());
+#endif
+
+ return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp
index 7cdfb4da08e4d..0731beb07f0d5 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp
@@ -18,6 +18,9 @@
#include <cassert>
#include "test_macros.h"
+#if TEST_STD_VER >= 26
+# include "copy_move_types.h"
+#endif
#include "test_iterators.h"
#include "../overload_compare_iterator.h"
@@ -55,6 +58,26 @@ int ThrowsCounted::count = 0;
int ThrowsCounted::constructed = 0;
int ThrowsCounted::throw_after = 0;
+#if TEST_STD_VER >= 26
+TEST_CONSTEXPR_CXX26 bool test() {
+ const int N = 3;
+ MutableMove in[N] = {MutableMove(1), MutableMove(2), MutableMove(3)};
+ std::allocator<MutableMove> alloc;
+ MutableMove* out = alloc.allocate(N);
+
+ auto result = std::uninitialized_move_n(in, N, out);
+ assert(result.first == in + N);
+ assert(result.second == out + N);
+ for (int i = 0; i != N; ++i)
+ assert(out[i].val == i + 1);
+
+ std::destroy(out, out + N);
+ alloc.deallocate(out, N);
+
+ return true;
+}
+#endif // TEST_STD_VER >= 26
+
void test_ctor_throws()
{
#ifndef TEST_HAS_NO_EXCEPTIONS
@@ -144,5 +167,10 @@ int main(int, char**)
}
}
+#if TEST_STD_VER >= 26
+ test();
+ static_assert(test());
+#endif
+
return 0;
}
>From 9ba0967c57c9e41e5e60b29a7bc7494c994cf690 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 12 May 2026 17:55:42 -0400
Subject: [PATCH 03/18] release note
---
libcxx/docs/ReleaseNotes/23.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index a55869a8bf783..e7c78fb88f91b 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -48,6 +48,7 @@ Implemented Papers
- P2164R9: ``views::enumerate`` (`Github <https://llvm.org/PR105251>`__)
- P2322R6: ``ranges::fold`` (`Github <https://llvm.org/PR105208>`__)
- P4144R1: Remove ``span``'s ``initializer_list`` constructor for C++26 (`Github <https://llvm.org/PR189612>`__)
+- P3508R0: Wording for "constexpr for specialized memory algorithms" (`Github <https://llvm.org/PR118379>`__)
Improvements and New Features
-----------------------------
>From 2d096c6b759fd7005ab54c9aea26606079beafd4 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 12 May 2026 18:02:45 -0400
Subject: [PATCH 04/18] feature macro
---
libcxx/include/version | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libcxx/include/version b/libcxx/include/version
index 1c683b67e5700..24ba697eac061 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -369,7 +369,11 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_not_fn 201603L
# define __cpp_lib_optional 201606L
// # define __cpp_lib_parallel_algorithm 201603L
+#if _LIBCPP_STD_VER >= 26
+# define __cpp_lib_raw_memory_algorithms 202406L
+#else
# define __cpp_lib_raw_memory_algorithms 201606L
+#endif
# define __cpp_lib_sample 201603L
# if _LIBCPP_HAS_THREADS
# define __cpp_lib_scoped_lock 201703L
>From 1ea959b9c889f4cfcbce13b9b3d88e284f6109f0 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 12 May 2026 18:03:27 -0400
Subject: [PATCH 05/18] format
---
.../uninitialized.copy/uninitialized_copy.pass.cpp | 2 +-
.../uninitialized.fill.n/uninitialized_fill_n.pass.cpp | 2 +-
.../uninitialized.fill/uninitialized_fill.pass.cpp | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp
index 4a25d4c1025d5..a11dc4fa882df 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp
@@ -142,5 +142,5 @@ int main(int, char**)
static_assert(test());
#endif
- return 0;
+ return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp
index 09fd8a78332f2..3e182fe2ec877 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp
@@ -112,5 +112,5 @@ int main(int, char**)
static_assert(test());
#endif
- return 0;
+ return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp
index 5e5633b0106d6..d655a3fc0bb25 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp
@@ -108,5 +108,5 @@ int main(int, char**)
static_assert(test());
#endif
- return 0;
+ return 0;
}
>From dae7110e6029ae86d02ccf908ea536de36d657c7 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 12 May 2026 18:03:36 -0400
Subject: [PATCH 06/18] ditto
---
.../uninitialized.move/uninitialized_move_n.pass.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp
index 0731beb07f0d5..429d01c8e79cf 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp
@@ -172,5 +172,5 @@ int main(int, char**)
static_assert(test());
#endif
- return 0;
+ return 0;
}
>From 0f66c317413d7c5ce38e7eea962b4c03c5db6d50 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 12 May 2026 18:05:22 -0400
Subject: [PATCH 07/18] feature macro
---
libcxx/include/version | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/libcxx/include/version b/libcxx/include/version
index 24ba697eac061..99f87f7bd5c6f 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -223,7 +223,7 @@ __cpp_lib_ranges_stride 202207L <ranges>
__cpp_lib_ranges_to_container 202202L <ranges>
__cpp_lib_ranges_zip 202110L <ranges> <tuple> <utility>
__cpp_lib_ratio 202306L <ratio>
-__cpp_lib_raw_memory_algorithms 201606L <memory>
+__cpp_lib_raw_memory_algorithms 202406L <memory>
__cpp_lib_rcu 202306L <rcu>
__cpp_lib_reference_from_temporary 202202L <type_traits>
__cpp_lib_reference_wrapper 202403L <functional>
@@ -369,11 +369,7 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_not_fn 201603L
# define __cpp_lib_optional 201606L
// # define __cpp_lib_parallel_algorithm 201603L
-#if _LIBCPP_STD_VER >= 26
# define __cpp_lib_raw_memory_algorithms 202406L
-#else
-# define __cpp_lib_raw_memory_algorithms 201606L
-#endif
# define __cpp_lib_sample 201603L
# if _LIBCPP_HAS_THREADS
# define __cpp_lib_scoped_lock 201703L
>From b97ef4163b28fec2332e44aa6e296ed6cd3017fd Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 12 May 2026 18:15:02 -0400
Subject: [PATCH 08/18] feature macro again
---
libcxx/include/version | 4 +++-
libcxx/utils/generate_feature_test_macro_components.py | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/version b/libcxx/include/version
index 99f87f7bd5c6f..2853f66d1e145 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -369,7 +369,7 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_not_fn 201603L
# define __cpp_lib_optional 201606L
// # define __cpp_lib_parallel_algorithm 201603L
-# define __cpp_lib_raw_memory_algorithms 202406L
+# define __cpp_lib_raw_memory_algorithms 201606L
# define __cpp_lib_sample 201603L
# if _LIBCPP_HAS_THREADS
# define __cpp_lib_scoped_lock 201703L
@@ -636,6 +636,8 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_tuple_like 202311L
# undef __cpp_lib_variant
# define __cpp_lib_variant 202306L
+# undef __cpp_lib_raw_memory_algorithms
+# define __cpp_lib_raw_memory_algorithms 202406L
#endif
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 2c1f92992bf1a..603cc1512b0f2 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1200,7 +1200,7 @@ def add_version_header(tc):
},
{
"name": "__cpp_lib_raw_memory_algorithms",
- "values": {"c++17": 201606},
+ "values": {"c++17": 201606, "c++26": 202406},
"headers": ["memory"],
},
{
>From c664c40d34ee442873848bcb1e26e1b8c8264a36 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 12 May 2026 18:21:25 -0400
Subject: [PATCH 09/18] feature macros x3
---
libcxx/docs/FeatureTestMacroTable.rst | 5 ++++-
libcxx/include/version | 5 +++--
.../support.limits.general/memory.version.compile.pass.cpp | 4 ++--
.../support.limits.general/version.version.compile.pass.cpp | 4 ++--
4 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 0d455beacd6df..4160bfc53162f 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -138,7 +138,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_parallel_algorithm`` *unimplemented*
---------------------------------------------------------- -----------------
- ``__cpp_lib_raw_memory_algorithms`` ``202406L``
+ ``__cpp_lib_raw_memory_algorithms`` ``201606L``
---------------------------------------------------------- -----------------
``__cpp_lib_sample`` ``201603L``
---------------------------------------------------------- -----------------
@@ -512,6 +512,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_ratio`` ``202306L``
---------------------------------------------------------- -----------------
+ ``__cpp_lib_raw_memory_algorithms`` ``202406L``
+ ---------------------------------------------------------- -----------------
``__cpp_lib_rcu`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_reference_wrapper`` ``202403L``
@@ -542,3 +544,4 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_variant`` ``202306L``
========================================================== =================
+
diff --git a/libcxx/include/version b/libcxx/include/version
index 2853f66d1e145..5da68a0317b90 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -224,6 +224,7 @@ __cpp_lib_ranges_to_container 202202L <ranges>
__cpp_lib_ranges_zip 202110L <ranges> <tuple> <utility>
__cpp_lib_ratio 202306L <ratio>
__cpp_lib_raw_memory_algorithms 202406L <memory>
+ 201606L // C++17
__cpp_lib_rcu 202306L <rcu>
__cpp_lib_reference_from_temporary 202202L <type_traits>
__cpp_lib_reference_wrapper 202403L <functional>
@@ -617,6 +618,8 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_ranges_concat 202403L
# define __cpp_lib_ranges_indices 202506L
# define __cpp_lib_ratio 202306L
+# undef __cpp_lib_raw_memory_algorithms
+# define __cpp_lib_raw_memory_algorithms 202406L
// # define __cpp_lib_rcu 202306L
# define __cpp_lib_reference_wrapper 202403L
# define __cpp_lib_saturation_arithmetic 202603L
@@ -636,8 +639,6 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_tuple_like 202311L
# undef __cpp_lib_variant
# define __cpp_lib_variant 202306L
-# undef __cpp_lib_raw_memory_algorithms
-# define __cpp_lib_raw_memory_algorithms 202406L
#endif
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
index f287e1ad9b3ad..69a51441d82db 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
@@ -623,8 +623,8 @@
# ifndef __cpp_lib_raw_memory_algorithms
# error "__cpp_lib_raw_memory_algorithms should be defined in c++26"
# endif
-# if __cpp_lib_raw_memory_algorithms != 201606L
-# error "__cpp_lib_raw_memory_algorithms should have the value 201606L in c++26"
+# if __cpp_lib_raw_memory_algorithms != 202406L
+# error "__cpp_lib_raw_memory_algorithms should have the value 202406L in c++26"
# endif
# ifndef __cpp_lib_shared_ptr_arrays
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 dfee4b6d458db..615eb6b71dccd 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
@@ -7811,8 +7811,8 @@
# ifndef __cpp_lib_raw_memory_algorithms
# error "__cpp_lib_raw_memory_algorithms should be defined in c++26"
# endif
-# if __cpp_lib_raw_memory_algorithms != 201606L
-# error "__cpp_lib_raw_memory_algorithms should have the value 201606L in c++26"
+# if __cpp_lib_raw_memory_algorithms != 202406L
+# error "__cpp_lib_raw_memory_algorithms should have the value 202406L in c++26"
# endif
# if !defined(_LIBCPP_VERSION)
>From fdbb4533ae4ada24d49cd30f95b202041bcd54b5 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 12 May 2026 21:26:20 -0400
Subject: [PATCH 10/18] Don't constexpr uninitialized_default_construct
---
.../include/__memory/ranges_uninitialized_algorithms.h | 8 +++-----
libcxx/include/__memory/uninitialized_algorithms.h | 9 +++------
2 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/libcxx/include/__memory/ranges_uninitialized_algorithms.h b/libcxx/include/__memory/ranges_uninitialized_algorithms.h
index 83e33527f35d3..703d3d92ff82c 100644
--- a/libcxx/include/__memory/ranges_uninitialized_algorithms.h
+++ b/libcxx/include/__memory/ranges_uninitialized_algorithms.h
@@ -44,16 +44,14 @@ namespace ranges {
struct __uninitialized_default_construct {
template <__nothrow_forward_iterator _ForwardIterator, __nothrow_sentinel_for<_ForwardIterator> _Sentinel>
requires default_initializable<iter_value_t<_ForwardIterator>>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
- operator()(_ForwardIterator __first, _Sentinel __last) const {
+ _LIBCPP_HIDE_FROM_ABI _ForwardIterator operator()(_ForwardIterator __first, _Sentinel __last) const {
using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>;
return std::__uninitialized_default_construct<_ValueType>(std::move(__first), std::move(__last));
}
template <__nothrow_forward_range _ForwardRange>
requires default_initializable<range_value_t<_ForwardRange>>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_iterator_t<_ForwardRange>
- operator()(_ForwardRange&& __range) const {
+ _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_ForwardRange> operator()(_ForwardRange&& __range) const {
return (*this)(ranges::begin(__range), ranges::end(__range));
}
};
@@ -67,7 +65,7 @@ inline constexpr auto uninitialized_default_construct = __uninitialized_default_
struct __uninitialized_default_construct_n {
template <__nothrow_forward_iterator _ForwardIterator>
requires default_initializable<iter_value_t<_ForwardIterator>>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
+ _LIBCPP_HIDE_FROM_ABI _ForwardIterator
operator()(_ForwardIterator __first, iter_difference_t<_ForwardIterator> __n) const {
using _ValueType = remove_reference_t<iter_reference_t<_ForwardIterator>>;
return std::__uninitialized_default_construct_n<_ValueType>(std::move(__first), __n);
diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h
index eded04eb06be0..70bf01846b35b 100644
--- a/libcxx/include/__memory/uninitialized_algorithms.h
+++ b/libcxx/include/__memory/uninitialized_algorithms.h
@@ -159,8 +159,7 @@ __uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) {
}
template <class _ForwardIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
-uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) {
+inline _LIBCPP_HIDE_FROM_ABI void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) {
using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
(void)std::__uninitialized_default_construct<_ValueType>(std::move(__first), std::move(__last));
}
@@ -168,8 +167,7 @@ uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __las
// uninitialized_default_construct_n
template <class _ValueType, class _ForwardIterator, class _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
-__uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
+inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
auto __idx = __first;
auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
for (; __n > 0; ++__idx, (void)--__n)
@@ -180,8 +178,7 @@ __uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
}
template <class _ForwardIterator, class _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
-uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
+inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
using _ValueType = typename iterator_traits<_ForwardIterator>::value_type;
return std::__uninitialized_default_construct_n<_ValueType>(std::move(__first), __n);
}
>From 99b8202b4a91de4dc2ffb587371feb2f325f0176 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 15 May 2026 19:22:09 -0400
Subject: [PATCH 11/18] Undo feature macro bump
---
libcxx/docs/FeatureTestMacroTable.rst | 3 ---
libcxx/include/version | 5 +----
libcxx/utils/generate_feature_test_macro_components.py | 2 +-
3 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 4160bfc53162f..609bb42889827 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -512,8 +512,6 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_ratio`` ``202306L``
---------------------------------------------------------- -----------------
- ``__cpp_lib_raw_memory_algorithms`` ``202406L``
- ---------------------------------------------------------- -----------------
``__cpp_lib_rcu`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_reference_wrapper`` ``202403L``
@@ -544,4 +542,3 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_variant`` ``202306L``
========================================================== =================
-
diff --git a/libcxx/include/version b/libcxx/include/version
index 5da68a0317b90..1c683b67e5700 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -223,8 +223,7 @@ __cpp_lib_ranges_stride 202207L <ranges>
__cpp_lib_ranges_to_container 202202L <ranges>
__cpp_lib_ranges_zip 202110L <ranges> <tuple> <utility>
__cpp_lib_ratio 202306L <ratio>
-__cpp_lib_raw_memory_algorithms 202406L <memory>
- 201606L // C++17
+__cpp_lib_raw_memory_algorithms 201606L <memory>
__cpp_lib_rcu 202306L <rcu>
__cpp_lib_reference_from_temporary 202202L <type_traits>
__cpp_lib_reference_wrapper 202403L <functional>
@@ -618,8 +617,6 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_ranges_concat 202403L
# define __cpp_lib_ranges_indices 202506L
# define __cpp_lib_ratio 202306L
-# undef __cpp_lib_raw_memory_algorithms
-# define __cpp_lib_raw_memory_algorithms 202406L
// # define __cpp_lib_rcu 202306L
# define __cpp_lib_reference_wrapper 202403L
# define __cpp_lib_saturation_arithmetic 202603L
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 603cc1512b0f2..2c1f92992bf1a 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1200,7 +1200,7 @@ def add_version_header(tc):
},
{
"name": "__cpp_lib_raw_memory_algorithms",
- "values": {"c++17": 201606, "c++26": 202406},
+ "values": {"c++17": 201606},
"headers": ["memory"],
},
{
>From f0562a1f3d91ec09c8a4d127a7ef61bc3bb17b02 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 15 May 2026 19:30:30 -0400
Subject: [PATCH 12/18] Remove constexpr from __uninitialized_default_construct
---
libcxx/include/__memory/uninitialized_algorithms.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h
index 70bf01846b35b..fa21f9e033374 100644
--- a/libcxx/include/__memory/uninitialized_algorithms.h
+++ b/libcxx/include/__memory/uninitialized_algorithms.h
@@ -147,7 +147,7 @@ uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) {
// uninitialized_default_construct
template <class _ValueType, class _ForwardIterator, class _Sentinel>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
+inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
__uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) {
auto __idx = __first;
auto __guard = std::__make_exception_guard([&] { std::__destroy(__first, __idx); });
>From 9977ba24c3ce29c08d1390e43e33c9e0c2552e8f Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 15 May 2026 19:38:26 -0400
Subject: [PATCH 13/18] Add tests for value_construct_n, sweep in existing
tests that are constexpr friendly
---
...ges_uninitialized_value_construct.pass.cpp | 70 ++++++++++++++-----
...s_uninitialized_value_construct_n.pass.cpp | 57 ++++++++++-----
.../uninitialized_value_construct.pass.cpp | 58 ++++++++++-----
.../uninitialized_value_construct_n.pass.cpp | 61 ++++++++++------
4 files changed, 173 insertions(+), 73 deletions(-)
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct.pass.cpp
index 6bab25ca38475..e577baaf27082 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct.pass.cpp
@@ -41,6 +41,54 @@ struct NotDefaultCtrable {
static_assert(
!std::is_invocable_v<decltype(std::ranges::uninitialized_value_construct), NotDefaultCtrable*, NotDefaultCtrable*>);
+TEST_CONSTEXPR_CXX26 bool test() {
+ constexpr int n = 3;
+ std::allocator<int> alloc;
+
+ // (iter, sentinel) overload.
+ {
+ int* out = alloc.allocate(n);
+ auto result = std::ranges::uninitialized_value_construct(out, out + n);
+ assert(result == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i] == 0);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ // (range) overload.
+ {
+ int* out = alloc.allocate(n);
+ auto out_range = std::ranges::subrange(out, out + n);
+ auto result = std::ranges::uninitialized_value_construct(out_range);
+ assert(result == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i] == 0);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ // Any existing values should be overwritten by value constructors.
+ {
+ constexpr int N = 5;
+ int buffer[N] = {42, 42, 42, 42, 42};
+
+ std::ranges::uninitialized_value_construct(buffer, buffer + 1);
+ assert(buffer[0] == 0);
+ assert(buffer[1] == 42);
+
+ std::ranges::uninitialized_value_construct(buffer, buffer + N);
+ assert(buffer[0] == 0);
+ assert(buffer[1] == 0);
+ assert(buffer[2] == 0);
+ assert(buffer[3] == 0);
+ assert(buffer[4] == 0);
+ }
+ return true;
+}
+
int main(int, char**) {
// An empty range -- no default constructors should be invoked.
{
@@ -132,23 +180,6 @@ int main(int, char**) {
Counted::reset();
}
- // Any existing values should be overwritten by value constructors.
- {
- constexpr int N = 5;
- int buffer[N] = {42, 42, 42, 42, 42};
-
- std::ranges::uninitialized_value_construct(buffer, buffer + 1);
- assert(buffer[0] == 0);
- assert(buffer[1] == 42);
-
- std::ranges::uninitialized_value_construct(buffer, buffer + N);
- assert(buffer[0] == 0);
- assert(buffer[1] == 0);
- assert(buffer[2] == 0);
- assert(buffer[3] == 0);
- assert(buffer[4] == 0);
- }
-
// An exception is thrown while objects are being created -- the existing objects should stay
// valid. (iterator, sentinel) overload.
#ifndef TEST_HAS_NO_EXCEPTIONS
@@ -183,5 +214,10 @@ int main(int, char**) {
}
#endif // TEST_HAS_NO_EXCEPTIONS
+ test();
+#if TEST_STD_VER >= 26
+ static_assert(test());
+#endif // TEST_STD_VER >= 26
+
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct_n.pass.cpp
index ac8f8f1173fd1..d240072b8259f 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct_n.pass.cpp
@@ -36,6 +36,41 @@ struct NotDefaultCtrable {
};
static_assert(!std::is_invocable_v<decltype(std::ranges::uninitialized_value_construct_n), NotDefaultCtrable*, int>);
+TEST_CONSTEXPR_CXX26 bool test() {
+ {
+ constexpr int n = 3;
+ std::allocator<int> alloc;
+ int* out = alloc.allocate(n);
+
+ auto result = std::ranges::uninitialized_value_construct_n(out, n);
+ assert(result == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i] == 0);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ // Any existing values should be overwritten by value constructors.
+ {
+ constexpr int N = 5;
+ int buffer[N] = {42, 42, 42, 42, 42};
+
+ std::ranges::uninitialized_value_construct_n(buffer, 1);
+ assert(buffer[0] == 0);
+ assert(buffer[1] == 42);
+
+ std::ranges::uninitialized_value_construct_n(buffer, N);
+ assert(buffer[0] == 0);
+ assert(buffer[1] == 0);
+ assert(buffer[2] == 0);
+ assert(buffer[3] == 0);
+ assert(buffer[4] == 0);
+ }
+
+ return true;
+}
+
int main(int, char**) {
// An empty range -- no default constructors should be invoked.
{
@@ -59,23 +94,6 @@ int main(int, char**) {
Counted::reset();
}
- // Any existing values should be overwritten by value constructors.
- {
- constexpr int N = 5;
- int buffer[N] = {42, 42, 42, 42, 42};
-
- std::ranges::uninitialized_value_construct_n(buffer, 1);
- assert(buffer[0] == 0);
- assert(buffer[1] == 42);
-
- std::ranges::uninitialized_value_construct_n(buffer, N);
- assert(buffer[0] == 0);
- assert(buffer[1] == 0);
- assert(buffer[2] == 0);
- assert(buffer[3] == 0);
- assert(buffer[4] == 0);
- }
-
// An exception is thrown while objects are being created -- the existing objects should stay
// valid.
#ifndef TEST_HAS_NO_EXCEPTIONS
@@ -95,5 +113,10 @@ int main(int, char**) {
}
#endif // TEST_HAS_NO_EXCEPTIONS
+ test();
+#if TEST_STD_VER >= 26
+ static_assert(test());
+#endif
+
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp
index e24b693c0ab0e..daf16ce3d0e5c 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp
@@ -53,6 +53,38 @@ int ThrowsCounted::count = 0;
int ThrowsCounted::constructed = 0;
int ThrowsCounted::throw_after = 0;
+TEST_CONSTEXPR_CXX26 bool test() {
+ {
+ const int n = 3;
+ std::allocator<int> alloc;
+ int* out = alloc.allocate(n);
+
+ std::uninitialized_value_construct(out, out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i] == 0);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ {
+ using It = forward_iterator<int*>;
+ const int N = 5;
+ int pool[N] = {-1, -1, -1, -1, -1};
+ int* p = pool;
+ std::uninitialized_value_construct(It(p), It(p + 1));
+ assert(pool[0] == 0);
+ assert(pool[1] == -1);
+ std::uninitialized_value_construct(It(p + 1), It(p + N));
+ assert(pool[1] == 0);
+ assert(pool[2] == 0);
+ assert(pool[3] == 0);
+ assert(pool[4] == 0);
+ }
+
+ return true;
+}
+
void test_ctor_throws()
{
#ifndef TEST_HAS_NO_EXCEPTIONS
@@ -86,27 +118,15 @@ void test_counted()
assert(Counted::count == 0);
}
-void test_value_initialized()
-{
- using It = forward_iterator<int*>;
- const int N = 5;
- int pool[N] = {-1, -1, -1, -1, -1};
- int* p = pool;
- std::uninitialized_value_construct(It(p), It(p+1));
- assert(pool[0] == 0);
- assert(pool[1] == -1);
- std::uninitialized_value_construct(It(p+1), It(p+N));
- assert(pool[1] == 0);
- assert(pool[2] == 0);
- assert(pool[3] == 0);
- assert(pool[4] == 0);
-}
-
int main(int, char**)
{
- test_counted();
- test_value_initialized();
- test_ctor_throws();
+ test_counted();
+ test_ctor_throws();
+
+ test();
+#if TEST_STD_VER >= 26
+ static_assert(test());
+#endif // TEST_STD_VER >= 26
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp
index cc7638d60abe5..e0759bba885a9 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp
@@ -52,6 +52,41 @@ int ThrowsCounted::count = 0;
int ThrowsCounted::constructed = 0;
int ThrowsCounted::throw_after = 0;
+TEST_CONSTEXPR_CXX26 bool test() {
+ {
+ const int n = 3;
+ std::allocator<int> alloc;
+ int* out = alloc.allocate(n);
+
+ int* result = std::uninitialized_value_construct_n(out, n);
+ assert(result == out + n);
+ for (int i = 0; i != n; ++i)
+ assert(out[i] == 0);
+
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
+ }
+
+ {
+ using It = forward_iterator<int*>;
+ const int N = 5;
+ int pool[N] = {-1, -1, -1, -1, -1};
+ int* p = pool;
+ It e = std::uninitialized_value_construct_n(It(p), 1);
+ assert(e == It(p + 1));
+ assert(pool[0] == 0);
+ assert(pool[1] == -1);
+ e = std::uninitialized_value_construct_n(It(p + 1), 4);
+ assert(e == It(p + N));
+ assert(pool[1] == 0);
+ assert(pool[2] == 0);
+ assert(pool[3] == 0);
+ assert(pool[4] == 0);
+ }
+
+ return true;
+}
+
void test_ctor_throws()
{
#ifndef TEST_HAS_NO_EXCEPTIONS
@@ -89,28 +124,14 @@ void test_counted()
assert(Counted::count == 0);
}
-void test_value_initialized()
-{
- using It = forward_iterator<int*>;
- const int N = 5;
- int pool[N] = {-1, -1, -1, -1, -1};
- int* p = pool;
- It e = std::uninitialized_value_construct_n(It(p), 1);
- assert(e == It(p+1));
- assert(pool[0] == 0);
- assert(pool[1] == -1);
- e = std::uninitialized_value_construct_n(It(p+1), 4);
- assert(e == It(p+N));
- assert(pool[1] == 0);
- assert(pool[2] == 0);
- assert(pool[3] == 0);
- assert(pool[4] == 0);
-}
-
int main(int, char**)
{
test_counted();
- test_value_initialized();
- return 0;
+ test();
+#if TEST_STD_VER >= 26
+ static_assert(test());
+#endif // TEST_STD_VER >= 26
+
+ return 0;
}
>From 17d14b8caa212b5bb5d072e4a043b400dc3bbde3 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 15 May 2026 19:49:39 -0400
Subject: [PATCH 14/18] generate files, undo stray removed newline
---
libcxx/docs/FeatureTestMacroTable.rst | 1 +
.../support.limits.general/memory.version.compile.pass.cpp | 4 ++--
.../support.limits.general/version.version.compile.pass.cpp | 4 ++--
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 609bb42889827..ae48eaed1f46b 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -542,3 +542,4 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_variant`` ``202306L``
========================================================== =================
+
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
index 69a51441d82db..f287e1ad9b3ad 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
@@ -623,8 +623,8 @@
# ifndef __cpp_lib_raw_memory_algorithms
# error "__cpp_lib_raw_memory_algorithms should be defined in c++26"
# endif
-# if __cpp_lib_raw_memory_algorithms != 202406L
-# error "__cpp_lib_raw_memory_algorithms should have the value 202406L in c++26"
+# if __cpp_lib_raw_memory_algorithms != 201606L
+# error "__cpp_lib_raw_memory_algorithms should have the value 201606L in c++26"
# endif
# ifndef __cpp_lib_shared_ptr_arrays
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 615eb6b71dccd..dfee4b6d458db 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
@@ -7811,8 +7811,8 @@
# ifndef __cpp_lib_raw_memory_algorithms
# error "__cpp_lib_raw_memory_algorithms should be defined in c++26"
# endif
-# if __cpp_lib_raw_memory_algorithms != 202406L
-# error "__cpp_lib_raw_memory_algorithms should have the value 202406L in c++26"
+# if __cpp_lib_raw_memory_algorithms != 201606L
+# error "__cpp_lib_raw_memory_algorithms should have the value 201606L in c++26"
# endif
# if !defined(_LIBCPP_VERSION)
>From 96be5890c84844aef0f8dd08d87c8920cb5cdfe6 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 15 May 2026 19:53:19 -0400
Subject: [PATCH 15/18] Formatting
---
.../uninitialized_value_construct_n.pass.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp
index e0759bba885a9..f7a88dd971df0 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct_n.pass.cpp
@@ -126,12 +126,12 @@ void test_counted()
int main(int, char**)
{
- test_counted();
+ test_counted();
- test();
+ test();
#if TEST_STD_VER >= 26
- static_assert(test());
+ static_assert(test());
#endif // TEST_STD_VER >= 26
- return 0;
+ return 0;
}
>From e3d4801ac1db18f8c4e2e8e0f1a1baa16d612462 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 19 May 2026 21:37:17 -0400
Subject: [PATCH 16/18] Use existing MoveOnly helper, move another range move
test to constexpr
---
.../ranges_uninitialized_move.pass.cpp | 30 ++++++++--------
.../uninitialized_move.pass.cpp | 32 ++++++++---------
.../uninitialized_move_n.pass.cpp | 34 +++++++++----------
3 files changed, 46 insertions(+), 50 deletions(-)
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move.pass.cpp
index d37d49918ac05..85259cc20998a 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/ranges_uninitialized_move.pass.cpp
@@ -92,6 +92,21 @@ TEST_CONSTEXPR_CXX26 bool test() {
alloc.deallocate(out, m);
}
+ // Any existing values should be overwritten by move constructors.
+ {
+ constexpr int N = 5;
+ int in[N] = {1, 2, 3, 4, 5};
+ int out[N] = {6, 7, 8, 9, 10};
+ assert(!std::equal(in, in + N, out, out + N));
+
+ std::ranges::uninitialized_move(in, in + 1, out, out + N);
+ assert(out[0] == 1);
+ assert(out[1] == 7);
+
+ std::ranges::uninitialized_move(in, in + N, out, out + N);
+ assert(std::equal(in, in + N, out, out + N));
+ }
+
return true;
}
@@ -265,21 +280,6 @@ int main(int, char**) {
}
Counted::reset();
- // Any existing values should be overwritten by move constructors.
- {
- constexpr int N = 5;
- int in[N] = {1, 2, 3, 4, 5};
- int out[N] = {6, 7, 8, 9, 10};
- assert(!std::equal(in, in + N, out, out + N));
-
- std::ranges::uninitialized_move(in, in + 1, out, out + N);
- assert(out[0] == 1);
- assert(out[1] == 7);
-
- std::ranges::uninitialized_move(in, in + N, out, out + N);
- assert(std::equal(in, in + N, out, out + N));
- }
-
// An exception is thrown while objects are being created -- check that the objects in the source
// range have been moved from. (iterator, sentinel) overload.
#ifndef TEST_HAS_NO_EXCEPTIONS
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp
index c0716a69a24d7..13fef7a972e95 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp
@@ -17,10 +17,8 @@
#include <cstdlib>
#include <cassert>
+#include "MoveOnly.h"
#include "test_macros.h"
-#if TEST_STD_VER >= 26
-# include "copy_move_types.h"
-#endif
#include "test_iterators.h"
#include "../overload_compare_iterator.h"
@@ -58,24 +56,24 @@ int ThrowsCounted::count = 0;
int ThrowsCounted::constructed = 0;
int ThrowsCounted::throw_after = 0;
-#if TEST_STD_VER >= 26
TEST_CONSTEXPR_CXX26 bool test() {
- const int N = 3;
- MutableMove in[N] = {MutableMove(1), MutableMove(2), MutableMove(3)};
- std::allocator<MutableMove> alloc;
- MutableMove* out = alloc.allocate(N);
-
- MutableMove* result = std::uninitialized_move(in, in + N, out);
- assert(result == out + N);
- for (int i = 0; i != N; ++i)
- assert(out[i].val == i + 1);
+ const int n = 3;
+ MoveOnly in[n] = {1, 2, 3};
+ std::allocator<MoveOnly> alloc;
+ MoveOnly* out = alloc.allocate(n);
+
+ MoveOnly* result = std::uninitialized_move(in, in + n, out);
+ assert(result == out + n);
+ for (int i = 0; i < n; ++i) {
+ assert(in[i] == 0);
+ assert(out[i] == i + 1);
+ }
- std::destroy(out, out + N);
- alloc.deallocate(out, N);
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
return true;
}
-#endif // TEST_STD_VER >= 26
void test_ctor_throws()
{
@@ -163,8 +161,8 @@ int main(int, char**) {
}
}
-#if TEST_STD_VER >= 26
test();
+#if TEST_STD_VER >= 26
static_assert(test());
#endif
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp
index 429d01c8e79cf..785cfb406efd9 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp
@@ -17,10 +17,8 @@
#include <cstdlib>
#include <cassert>
+#include "MoveOnly.h"
#include "test_macros.h"
-#if TEST_STD_VER >= 26
-# include "copy_move_types.h"
-#endif
#include "test_iterators.h"
#include "../overload_compare_iterator.h"
@@ -58,25 +56,25 @@ int ThrowsCounted::count = 0;
int ThrowsCounted::constructed = 0;
int ThrowsCounted::throw_after = 0;
-#if TEST_STD_VER >= 26
TEST_CONSTEXPR_CXX26 bool test() {
- const int N = 3;
- MutableMove in[N] = {MutableMove(1), MutableMove(2), MutableMove(3)};
- std::allocator<MutableMove> alloc;
- MutableMove* out = alloc.allocate(N);
-
- auto result = std::uninitialized_move_n(in, N, out);
- assert(result.first == in + N);
- assert(result.second == out + N);
- for (int i = 0; i != N; ++i)
- assert(out[i].val == i + 1);
+ const int n = 3;
+ MoveOnly in[n] = {1, 2, 3};
+ std::allocator<MoveOnly> alloc;
+ MoveOnly* out = alloc.allocate(n);
+
+ auto result = std::uninitialized_move_n(in, n, out);
+ assert(result.first == in + n);
+ assert(result.second == out + n);
+ for (int i = 0; i < n; ++i) {
+ assert(in[i] == 0);
+ assert(out[i] == i + 1);
+ }
- std::destroy(out, out + N);
- alloc.deallocate(out, N);
+ std::destroy(out, out + n);
+ alloc.deallocate(out, n);
return true;
}
-#endif // TEST_STD_VER >= 26
void test_ctor_throws()
{
@@ -167,8 +165,8 @@ int main(int, char**)
}
}
-#if TEST_STD_VER >= 26
test();
+#if TEST_STD_VER >= 26
static_assert(test());
#endif
>From 812c9c7b3ef9d694e89c83037e40894a1e80ce47 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 24 May 2026 15:58:39 -0400
Subject: [PATCH 17/18] Include copy_move_types unconditionally, use backported
destroy algo
---
.../uninitialized.copy/uninitialized_copy.pass.cpp | 11 ++++-------
.../uninitialized_copy_n.pass.cpp | 13 +++++--------
.../uninitialized.fill/uninitialized_fill.pass.cpp | 11 ++++-------
3 files changed, 13 insertions(+), 22 deletions(-)
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp
index a11dc4fa882df..7f9706edc2ce0 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy.pass.cpp
@@ -16,10 +16,9 @@
#include <memory>
#include <cassert>
+#include "copy_move_types.h"
+#include "../destroy.h"
#include "test_macros.h"
-#if TEST_STD_VER >= 26
-# include "copy_move_types.h"
-#endif
#include "../overload_compare_iterator.h"
struct B
@@ -51,7 +50,6 @@ struct Nasty
int Nasty::counter_ = 0;
-#if TEST_STD_VER >= 26
TEST_CONSTEXPR_CXX26 bool test() {
const int n = 3;
const ConstCopy in[n] = {ConstCopy(1), ConstCopy(2), ConstCopy(3)};
@@ -63,12 +61,11 @@ TEST_CONSTEXPR_CXX26 bool test() {
for (int i = 0; i != n; ++i)
assert(out[i].val == in[i].val);
- std::destroy(out, out + n);
+ backport::destroy(out, out + n);
alloc.deallocate(out, n);
return true;
}
-#endif // TEST_STD_VER >= 26
int main(int, char**)
{
@@ -137,8 +134,8 @@ int main(int, char**)
}
}
-#if TEST_STD_VER >= 26
test();
+#if TEST_STD_VER >= 26
static_assert(test());
#endif
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp
index e725c42a14733..f42efecfaf8af 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.copy/uninitialized_copy_n.pass.cpp
@@ -16,10 +16,9 @@
#include <memory>
#include <cassert>
+#include "copy_move_types.h"
+#include "../destroy.h"
#include "test_macros.h"
-#if TEST_STD_VER >= 26
-# include "copy_move_types.h"
-#endif
#include "../overload_compare_iterator.h"
struct B
@@ -51,7 +50,6 @@ struct Nasty
int Nasty::counter_ = 0;
-#if TEST_STD_VER >= 26
TEST_CONSTEXPR_CXX26 bool test() {
const int n = 3;
const ConstCopy in[n] = {ConstCopy(1), ConstCopy(2), ConstCopy(3)};
@@ -63,12 +61,11 @@ TEST_CONSTEXPR_CXX26 bool test() {
for (int i = 0; i != n; ++i)
assert(out[i].val == in[i].val);
- std::destroy(out, out + n);
+ backport::destroy(out, out + n);
alloc.deallocate(out, n);
return true;
}
-#endif // TEST_STD_VER >= 26
int main(int, char**)
{
@@ -137,10 +134,10 @@ int main(int, char**)
}
}
-#if TEST_STD_VER >= 26
test();
+#if TEST_STD_VER >= 26
static_assert(test());
-#endif // TEST_STD_VER >= 26
+#endif
return 0;
}
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp
index d655a3fc0bb25..1ae1c7e1b0bd4 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/uninitialized_fill.pass.cpp
@@ -16,10 +16,9 @@
#include <memory>
#include <cassert>
+#include "copy_move_types.h"
+#include "../destroy.h"
#include "test_macros.h"
-#if TEST_STD_VER >= 26
-# include "copy_move_types.h"
-#endif
struct B
{
@@ -50,7 +49,6 @@ struct Nasty
int Nasty::counter_ = 0;
-#if TEST_STD_VER >= 26
TEST_CONSTEXPR_CXX26 bool test() {
int n = 3;
ConstCopy value(42);
@@ -61,12 +59,11 @@ TEST_CONSTEXPR_CXX26 bool test() {
for (int i = 0; i != n; ++i)
assert(out[i].val == value.val);
- std::destroy(out, out + n);
+ backport::destroy(out, out + n);
alloc.deallocate(out, n);
return true;
}
-#endif // TEST_STD_VER >= 26
int main(int, char**)
{
@@ -103,8 +100,8 @@ int main(int, char**)
assert(bp[i].i_ == 23);
}
-#if TEST_STD_VER >= 26
test();
+#if TEST_STD_VER >= 26
static_assert(test());
#endif
>From 4e1f25af2e34a8ef30325938917b193ff842c2ec Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 24 May 2026 16:08:08 -0400
Subject: [PATCH 18/18] Ditto
---
.../uninitialized_fill_n.pass.cpp | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp
index 3e182fe2ec877..e837da88114c2 100644
--- a/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp
+++ b/libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill.n/uninitialized_fill_n.pass.cpp
@@ -15,10 +15,9 @@
#include <memory>
#include <cassert>
+#include "copy_move_types.h"
+#include "../destroy.h"
#include "test_macros.h"
-#if TEST_STD_VER >= 26
-# include "copy_move_types.h"
-#endif
struct B
{
@@ -49,7 +48,6 @@ struct Nasty
int Nasty::counter_ = 0;
-#if TEST_STD_VER >= 26
TEST_CONSTEXPR_CXX26 bool test() {
const int n = 3;
ConstCopy value(42);
@@ -61,12 +59,11 @@ TEST_CONSTEXPR_CXX26 bool test() {
for (int i = 0; i != n; ++i)
assert(out[i].val == value.val);
- std::destroy(out, out + n);
+ backport::destroy(out, out + n);
alloc.deallocate(out, n);
return true;
}
-#endif // TEST_STD_VER >= 26
int main(int, char**)
{
@@ -107,8 +104,8 @@ int main(int, char**)
}
-#if TEST_STD_VER >= 26
test();
+#if TEST_STD_VER >= 26
static_assert(test());
#endif
More information about the libcxx-commits
mailing list