Skip to content

Commit 82307bd

Browse files
committed
[P2283R1] Implement constexpr specialized memory algorithms
1 parent 6213792 commit 82307bd

26 files changed

Lines changed: 1935 additions & 164 deletions

File tree

stl/inc/memory

Lines changed: 242 additions & 121 deletions
Large diffs are not rendered by default.

stl/inc/xmemory

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,20 +1575,25 @@ namespace ranges {
15751575
template <input_iterator _It, sentinel_for<_It> _Se, _No_throw_forward_iterator _Out,
15761576
_No_throw_sentinel_for<_Out> _OSe>
15771577
requires constructible_from<iter_value_t<_Out>, iter_rvalue_reference_t<_It>>
1578-
uninitialized_move_result<_It, _Out> _Uninitialized_move_unchecked(
1578+
_CONSTEXPR23_DYNALLOC uninitialized_move_result<_It, _Out> _Uninitialized_move_unchecked(
15791579
_It _IFirst, const _Se _ILast, _Out _OFirst, const _OSe _OLast) {
15801580
// clang-format on
15811581
if constexpr (is_same_v<_Se, _It> && is_same_v<_OSe, _Out> && _Ptr_move_cat<_It, _Out>::_Really_trivial) {
1582-
return _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast);
1583-
} else {
1584-
_Uninitialized_backout _Backout{_STD move(_OFirst)};
1585-
1586-
for (; _IFirst != _ILast && _Backout._Last != _OLast; ++_IFirst) {
1587-
_Backout._Emplace_back(_RANGES iter_move(_IFirst));
1582+
#ifdef __cpp_lib_constexpr_dynamic_alloc
1583+
if (!_STD is_constant_evaluated())
1584+
#endif // __cpp_lib_constexpr_dynamic_alloc
1585+
{
1586+
return _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast);
15881587
}
1588+
}
1589+
1590+
_Uninitialized_backout _Backout{_STD move(_OFirst)};
15891591

1590-
return {_STD move(_IFirst), _Backout._Release()};
1592+
for (; _IFirst != _ILast && _Backout._Last != _OLast; ++_IFirst) {
1593+
_Backout._Emplace_back(_RANGES iter_move(_IFirst));
15911594
}
1595+
1596+
return {_STD move(_IFirst), _Backout._Release()};
15921597
}
15931598
} // namespace ranges
15941599
#endif // __cpp_lib_concepts
@@ -1680,8 +1685,9 @@ _CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_copy_unchecked(
16801685
return _Backout._Release();
16811686
}
16821687

1688+
16831689
template <class _InIt, class _NoThrowFwdIt>
1684-
_NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) {
1690+
_CONSTEXPR20_DYNALLOC _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) {
16851691
// copy [_First, _Last) to raw [_Dest, ...)
16861692
_Adl_verify_range(_First, _Last);
16871693
auto _UFirst = _Get_unwrapped(_First);
@@ -1755,28 +1761,39 @@ _CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n(
17551761

17561762
// FUNCTION TEMPLATE uninitialized_fill
17571763
template <class _NoThrowFwdIt, class _Tval>
1758-
void uninitialized_fill(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, const _Tval& _Val) {
1764+
_CONSTEXPR20_DYNALLOC void uninitialized_fill(
1765+
const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, const _Tval& _Val) {
17591766
// copy _Val throughout raw [_First, _Last)
17601767
_Adl_verify_range(_First, _Last);
17611768
auto _UFirst = _Get_unwrapped(_First);
17621769
const auto _ULast = _Get_unwrapped(_Last);
17631770
if constexpr (_Fill_memset_is_safe<_Unwrapped_t<const _NoThrowFwdIt&>, _Tval>) {
1764-
_Fill_memset(_UFirst, _Val, static_cast<size_t>(_ULast - _UFirst));
1765-
} else {
1766-
if constexpr (_Fill_zero_memset_is_safe<_Unwrapped_t<const _NoThrowFwdIt&>, _Tval>) {
1771+
#ifdef __cpp_lib_constexpr_dynamic_alloc
1772+
if (!_STD is_constant_evaluated())
1773+
#endif // __cpp_lib_constexpr_dynamic_alloc
1774+
{
1775+
_Fill_memset(_UFirst, _Val, static_cast<size_t>(_ULast - _UFirst));
1776+
return;
1777+
}
1778+
}
1779+
if constexpr (_Fill_zero_memset_is_safe<_Unwrapped_t<const _NoThrowFwdIt&>, _Tval>) {
1780+
#ifdef __cpp_lib_constexpr_dynamic_alloc
1781+
if (!_STD is_constant_evaluated())
1782+
#endif // __cpp_lib_constexpr_dynamic_alloc
1783+
{
17671784
if (_Is_all_bits_zero(_Val)) {
17681785
_Fill_zero_memset(_UFirst, static_cast<size_t>(_ULast - _UFirst));
17691786
return;
17701787
}
17711788
}
1789+
}
17721790

1773-
_Uninitialized_backout<_Unwrapped_t<const _NoThrowFwdIt&>> _Backout{_UFirst};
1774-
while (_Backout._Last != _ULast) {
1775-
_Backout._Emplace_back(_Val);
1776-
}
1777-
1778-
_Backout._Release();
1791+
_Uninitialized_backout<_Unwrapped_t<const _NoThrowFwdIt&>> _Backout{_UFirst};
1792+
while (_Backout._Last != _ULast) {
1793+
_Backout._Emplace_back(_Val);
17791794
}
1795+
1796+
_Backout._Release();
17801797
}
17811798

17821799
// FUNCTION TEMPLATE _Uninitialized_value_construct_n WITH ALLOCATOR
@@ -1819,19 +1836,23 @@ _CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_value_construct_n(
18191836
}
18201837

18211838
template <class _NoThrowFwdIt, class _Diff>
1822-
_NoThrowFwdIt _Uninitialized_value_construct_n_unchecked1(_NoThrowFwdIt _UFirst, _Diff _Count) {
1839+
_CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_value_construct_n_unchecked1(_NoThrowFwdIt _UFirst, _Diff _Count) {
18231840
// value-initialize all elements in [_UFirst, _UFirst + _Count_raw)
18241841
_STL_INTERNAL_CHECK(_Count >= 0);
18251842
if constexpr (_Use_memset_value_construct_v<_NoThrowFwdIt>) {
1826-
return _Zero_range(_UFirst, _UFirst + _Count);
1827-
} else {
1828-
_Uninitialized_backout<_NoThrowFwdIt> _Backout{_UFirst};
1829-
for (; 0 < _Count; --_Count) {
1830-
_Backout._Emplace_back();
1843+
#ifdef __cpp_lib_constexpr_dynamic_alloc
1844+
if (!_STD is_constant_evaluated())
1845+
#endif // __cpp_lib_constexpr_dynamic_alloc
1846+
{
1847+
return _Zero_range(_UFirst, _UFirst + _Count);
18311848
}
1832-
1833-
return _Backout._Release();
18341849
}
1850+
_Uninitialized_backout<_NoThrowFwdIt> _Backout{_UFirst};
1851+
for (; 0 < _Count; --_Count) {
1852+
_Backout._Emplace_back();
1853+
}
1854+
1855+
return _Backout._Release();
18351856
}
18361857

18371858
#if _HAS_DEPRECATED_TEMPORARY_BUFFER

stl/inc/xutility

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,18 @@ _NODISCARD constexpr void* _Voidify_iter(_Iter _It) noexcept {
135135
}
136136
}
137137

138+
// FUNCTION TEMPLATE default_construct_at
139+
#if _HAS_CXX20 // TRANSITION, _HAS_CXX23
140+
template <class _Ty, class = void_t<decltype(::new (_STD declval<void*>()) _Ty)>>
141+
#if 0 // TRANSITION, compiler suport
142+
_CONSTEXPR20_DYNALLOC
143+
#endif // compiler support
144+
_Ty* default_construct_at(_Ty* const _Location) noexcept(
145+
noexcept(::new (_Voidify_iter(_Location)) _Ty)) /* strengthened */ {
146+
return ::new (_Voidify_iter(_Location)) _Ty;
147+
}
148+
#endif // _HAS_CXX20
149+
138150
// FUNCTION TEMPLATE construct_at
139151
#if _HAS_CXX20
140152
template <class _Ty, class... _Types,
@@ -4454,7 +4466,7 @@ void _Fill_zero_memset(_CtgIt _Dest, const size_t _Count) {
44544466
}
44554467

44564468
template <class _Ty>
4457-
_NODISCARD bool _Is_all_bits_zero(const _Ty& _Val) {
4469+
_NODISCARD _CONSTEXPR23_DYNALLOC bool _Is_all_bits_zero(const _Ty& _Val) {
44584470
// checks if scalar type has all bits set to zero
44594471
_STL_INTERNAL_STATIC_ASSERT(is_scalar_v<_Ty> && !is_member_pointer_v<_Ty>);
44604472
constexpr _Ty _Zero{};

stl/inc/yvals_core.h

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,13 +1162,19 @@
11621162
#ifndef _M_CEE
11631163
#define __cpp_lib_parallel_algorithm 201603L
11641164
#endif // _M_CEE
1165-
#define __cpp_lib_raw_memory_algorithms 201606L
1166-
#define __cpp_lib_sample 201603L
1167-
#define __cpp_lib_scoped_lock 201703L
1168-
#define __cpp_lib_shared_ptr_weak_type 201606L
1169-
#define __cpp_lib_string_view 201803L
1170-
#define __cpp_lib_to_chars 201611L
1171-
#define __cpp_lib_variant 201606L
1165+
1166+
#if _HAS_CXX20 && defined(__cpp_lib_constexpr_dynamic_alloc) // TRANSITION, enable only in C++23 when available
1167+
#define __cpp_lib_raw_memory_algorithms 202106L
1168+
#else
1169+
#define __cpp_lib_raw_memory_algorithms 202106L
1170+
#endif
1171+
1172+
#define __cpp_lib_sample 201603L
1173+
#define __cpp_lib_scoped_lock 201703L
1174+
#define __cpp_lib_shared_ptr_weak_type 201606L
1175+
#define __cpp_lib_string_view 201803L
1176+
#define __cpp_lib_to_chars 201611L
1177+
#define __cpp_lib_variant 201606L
11721178
#endif // _HAS_CXX17
11731179

11741180
#if _HAS_CXX17
@@ -1325,6 +1331,13 @@
13251331
#define _CONSTEXPR20_CONTAINER inline
13261332
#endif
13271333

1334+
// Functions that became constexpr in C++23 via P2283
1335+
#ifdef __cpp_lib_constexpr_dynamic_alloc // TRANSITION, enable only in C++23 when available
1336+
#define _CONSTEXPR23_DYNALLOC constexpr
1337+
#else
1338+
#define _CONSTEXPR23_DYNALLOC inline
1339+
#endif
1340+
13281341
#ifdef _RTC_CONVERSION_CHECKS_ENABLED
13291342
#ifndef _ALLOW_RTCc_IN_STL
13301343
#error /RTCc rejects conformant code, so it is not supported by the C++ Standard Library. Either remove this \

tests/std/tests/P0896R4_ranges_alg_uninitialized_copy/test.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ struct memcpy_test {
215215
}
216216

217217
{ // Validate input shorter
218-
int input[] = {13, 55, 12345};
219-
int output[] = {-1, -1, -1, -1};
218+
int input[] = {13, 55, 12345};
219+
int output[4];
220220

221221
auto result = ranges::uninitialized_copy(input, output);
222222
assert(result.in == end(input));
@@ -226,8 +226,8 @@ struct memcpy_test {
226226
}
227227

228228
{ // Validate output shorter
229-
int input[] = {13, 55, 12345, 42};
230-
int output[] = {-1, -1, -1};
229+
int input[] = {13, 55, 12345, 42};
230+
int output[3];
231231

232232
auto result = ranges::uninitialized_copy(input, output);
233233
assert(++result.in == end(input));

tests/std/tests/P0896R4_ranges_alg_uninitialized_move/test.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ struct memcpy_test {
216216
}
217217

218218
{ // Validate input shorter
219-
int input[] = {13, 55, 12345};
220-
int output[] = {-1, -1, -1, -1};
219+
int input[] = {13, 55, 12345};
220+
int output[4];
221221

222222
auto result = ranges::uninitialized_move(input, output);
223223
assert(result.in == end(input));
@@ -227,8 +227,8 @@ struct memcpy_test {
227227
}
228228

229229
{ // Validate output shorter
230-
int input[] = {13, 55, 12345, 42};
231-
int output[] = {-1, -1, -1};
230+
int input[] = {13, 55, 12345, 42};
231+
int output[3];
232232

233233
auto result = ranges::uninitialized_move(input, output);
234234
assert(++result.in == end(input));
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
RUNALL_INCLUDE ..\concepts_matrix.lst

0 commit comments

Comments
 (0)