Skip to content

Commit 29c1e4a

Browse files
committed
[P2283R1] Implement constexpr specialized memory algorithms
1 parent 3c2fd04 commit 29c1e4a

File tree

21 files changed

+1676
-181
lines changed

21 files changed

+1676
-181
lines changed

stl/inc/memory

+218-140
Large diffs are not rendered by default.

stl/inc/xmemory

+53-34
Original file line numberDiff line numberDiff line change
@@ -1601,33 +1601,38 @@ namespace ranges {
16011601
template <input_iterator _It, sentinel_for<_It> _Se, _No_throw_forward_iterator _Out,
16021602
_No_throw_sentinel_for<_Out> _OSe>
16031603
requires (constructible_from<iter_value_t<_Out>, iter_rvalue_reference_t<_It>>)
1604-
uninitialized_move_result<_It, _Out> _Uninitialized_move_unchecked(
1604+
_CONSTEXPR23 uninitialized_move_result<_It, _Out> _Uninitialized_move_unchecked(
16051605
_It _IFirst, _Se _ILast, _Out _OFirst, _OSe _OLast) {
16061606
// clang-format on
16071607
constexpr bool _Is_sized1 = sized_sentinel_for<_Se, _It>;
16081608
constexpr bool _Is_sized2 = sized_sentinel_for<_OSe, _Out>;
16091609
if constexpr (_Iter_move_cat<_It, _Out>::_Bitcopy_constructible
16101610
&& _Sized_or_unreachable_sentinel_for<_Se, _It> //
16111611
&& _Sized_or_unreachable_sentinel_for<_OSe, _Out>) {
1612-
if constexpr (_Is_sized1 && _Is_sized2) {
1613-
return _Copy_memcpy_common(_IFirst, _RANGES next(_IFirst, _STD move(_ILast)), _OFirst,
1614-
_RANGES next(_OFirst, _STD move(_OLast)));
1615-
} else if constexpr (_Is_sized1) {
1616-
return _Copy_memcpy_distance(_IFirst, _OFirst, _IFirst, _RANGES next(_IFirst, _STD move(_ILast)));
1617-
} else if constexpr (_Is_sized2) {
1618-
return _Copy_memcpy_distance(_IFirst, _OFirst, _OFirst, _RANGES next(_OFirst, _STD move(_OLast)));
1619-
} else {
1620-
_STL_ASSERT(false, "Tried to uninitialized_move two ranges with unreachable sentinels");
1612+
#if _HAS_CXX23
1613+
if (!_STD is_constant_evaluated())
1614+
#endif // _HAS_CXX23
1615+
{
1616+
if constexpr (_Is_sized1 && _Is_sized2) {
1617+
return _Copy_memcpy_common(_IFirst, _RANGES next(_IFirst, _STD move(_ILast)), _OFirst,
1618+
_RANGES next(_OFirst, _STD move(_OLast)));
1619+
} else if constexpr (_Is_sized1) {
1620+
return _Copy_memcpy_distance(_IFirst, _OFirst, _IFirst, _RANGES next(_IFirst, _STD move(_ILast)));
1621+
} else if constexpr (_Is_sized2) {
1622+
return _Copy_memcpy_distance(_IFirst, _OFirst, _OFirst, _RANGES next(_OFirst, _STD move(_OLast)));
1623+
} else {
1624+
_STL_ASSERT(false, "Tried to uninitialized_move two ranges with unreachable sentinels");
1625+
}
16211626
}
1622-
} else {
1623-
_Uninitialized_backout _Backout{_STD move(_OFirst)};
1627+
}
16241628

1625-
for (; _IFirst != _ILast && _Backout._Last != _OLast; ++_IFirst) {
1626-
_Backout._Emplace_back(_RANGES iter_move(_IFirst));
1627-
}
1629+
_Uninitialized_backout _Backout{_STD move(_OFirst)};
16281630

1629-
return {_STD move(_IFirst), _Backout._Release()};
1631+
for (; _IFirst != _ILast && _Backout._Last != _OLast; ++_IFirst) {
1632+
_Backout._Emplace_back(_RANGES iter_move(_IFirst));
16301633
}
1634+
1635+
return {_STD move(_IFirst), _Backout._Release()};
16311636
}
16321637
} // namespace ranges
16331638
#endif // __cpp_lib_concepts
@@ -1715,7 +1720,7 @@ _CONSTEXPR20 _NoThrowFwdIt _Uninitialized_copy_unchecked(_InIt _First, const _In
17151720
}
17161721

17171722
template <class _InIt, class _NoThrowFwdIt>
1718-
_NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) {
1723+
_CONSTEXPR23 _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) {
17191724
// copy [_First, _Last) to raw [_Dest, ...)
17201725
_Adl_verify_range(_First, _Last);
17211726
auto _UFirst = _Get_unwrapped(_First);
@@ -1786,28 +1791,37 @@ _CONSTEXPR20 _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n(
17861791
}
17871792

17881793
template <class _NoThrowFwdIt, class _Tval>
1789-
void uninitialized_fill(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, const _Tval& _Val) {
1794+
_CONSTEXPR23 void uninitialized_fill(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, const _Tval& _Val) {
17901795
// copy _Val throughout raw [_First, _Last)
17911796
_Adl_verify_range(_First, _Last);
17921797
auto _UFirst = _Get_unwrapped(_First);
17931798
const auto _ULast = _Get_unwrapped(_Last);
17941799
if constexpr (_Fill_memset_is_safe<_Unwrapped_t<const _NoThrowFwdIt&>, _Tval>) {
1795-
_Fill_memset(_UFirst, _Val, static_cast<size_t>(_ULast - _UFirst));
1796-
} else {
1797-
if constexpr (_Fill_zero_memset_is_safe<_Unwrapped_t<const _NoThrowFwdIt&>, _Tval>) {
1800+
#if _HAS_CXX23
1801+
if (!_STD is_constant_evaluated())
1802+
#endif // _HAS_CXX23
1803+
{
1804+
_Fill_memset(_UFirst, _Val, static_cast<size_t>(_ULast - _UFirst));
1805+
return;
1806+
}
1807+
} else if constexpr (_Fill_zero_memset_is_safe<_Unwrapped_t<const _NoThrowFwdIt&>, _Tval>) {
1808+
#if _HAS_CXX23
1809+
if (!_STD is_constant_evaluated())
1810+
#endif // _HAS_CXX23
1811+
{
17981812
if (_Is_all_bits_zero(_Val)) {
17991813
_Fill_zero_memset(_UFirst, static_cast<size_t>(_ULast - _UFirst));
18001814
return;
18011815
}
18021816
}
1817+
}
18031818

1804-
_Uninitialized_backout<_Unwrapped_t<const _NoThrowFwdIt&>> _Backout{_UFirst};
1805-
while (_Backout._Last != _ULast) {
1806-
_Backout._Emplace_back(_Val);
1807-
}
1808-
1809-
_Backout._Release();
1819+
_Uninitialized_backout<_Unwrapped_t<const _NoThrowFwdIt&>> _Backout{_UFirst};
1820+
while (_Backout._Last != _ULast) {
1821+
_Backout._Emplace_back(_Val);
18101822
}
1823+
1824+
_Backout._Release();
18111825
}
18121826

18131827
template <class _NoThrowFwdIt>
@@ -1849,19 +1863,24 @@ _CONSTEXPR20 _Alloc_ptr_t<_Alloc> _Uninitialized_value_construct_n(
18491863
}
18501864

18511865
template <class _NoThrowFwdIt, class _Diff>
1852-
_NoThrowFwdIt _Uninitialized_value_construct_n_unchecked1(_NoThrowFwdIt _UFirst, _Diff _Count) {
1866+
_CONSTEXPR23 _NoThrowFwdIt _Uninitialized_value_construct_n_unchecked1(_NoThrowFwdIt _UFirst, _Diff _Count) {
18531867
// value-initialize all elements in [_UFirst, _UFirst + _Count_raw)
18541868
_STL_INTERNAL_CHECK(_Count >= 0);
18551869
if constexpr (_Use_memset_value_construct_v<_NoThrowFwdIt>) {
1856-
return _Zero_range(_UFirst, _UFirst + _Count);
1857-
} else {
1858-
_Uninitialized_backout<_NoThrowFwdIt> _Backout{_UFirst};
1859-
for (; 0 < _Count; --_Count) {
1860-
_Backout._Emplace_back();
1870+
#if _HAS_CXX23
1871+
if (!_STD is_constant_evaluated())
1872+
#endif // _HAS_CXX23
1873+
{
1874+
return _Zero_range(_UFirst, _UFirst + _Count);
18611875
}
1876+
}
18621877

1863-
return _Backout._Release();
1878+
_Uninitialized_backout<_NoThrowFwdIt> _Backout{_UFirst};
1879+
for (; 0 < _Count; --_Count) {
1880+
_Backout._Emplace_back();
18641881
}
1882+
1883+
return _Backout._Release();
18651884
}
18661885

18671886
#if _HAS_DEPRECATED_TEMPORARY_BUFFER

stl/inc/yvals_core.h

+20-6
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@
295295
// P2136R3 invoke_r()
296296
// P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr
297297
// P2186R2 Removing Garbage Collection Support
298+
// P2283R2 constexpr Specialized Memory Algorithms
298299

299300
// Parallel Algorithms Notes
300301
// C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms.
@@ -620,6 +621,13 @@
620621
#define _CONSTEXPR20 inline
621622
#endif // ^^^ inline (not constexpr) in C++17 and earlier ^^^
622623

624+
// Functions that became constexpr in C++23
625+
#if _HAS_CXX23
626+
#define _CONSTEXPR23 constexpr
627+
#else // ^^^ constexpr in C++23 and later / inline (not constexpr) in C++20 and earlier vvv
628+
#define _CONSTEXPR23 inline
629+
#endif // ^^^ inline (not constexpr) in C++20 and earlier ^^^
630+
623631
// P0607R0 Inline Variables For The STL
624632
#if _HAS_CXX17
625633
#define _INLINE_VAR inline
@@ -1219,12 +1227,12 @@
12191227
#ifndef _M_CEE
12201228
#define __cpp_lib_parallel_algorithm 201603L
12211229
#endif // _M_CEE
1222-
#define __cpp_lib_raw_memory_algorithms 201606L
1223-
#define __cpp_lib_sample 201603L
1224-
#define __cpp_lib_scoped_lock 201703L
1225-
#define __cpp_lib_shared_ptr_weak_type 201606L
1226-
#define __cpp_lib_string_view 201803L
1227-
#define __cpp_lib_to_chars 201611L
1230+
1231+
#define __cpp_lib_sample 201603L
1232+
#define __cpp_lib_scoped_lock 201703L
1233+
#define __cpp_lib_shared_ptr_weak_type 201606L
1234+
#define __cpp_lib_string_view 201803L
1235+
#define __cpp_lib_to_chars 201611L
12281236
#endif // _HAS_CXX17
12291237

12301238
// C++20
@@ -1390,6 +1398,12 @@
13901398
#define __cpp_lib_to_underlying 202102L
13911399
#endif // _HAS_CXX23
13921400

1401+
#if _HAS_CXX23
1402+
#define __cpp_lib_raw_memory_algorithms 202106L
1403+
#else // _HAS_CXX23
1404+
#define __cpp_lib_raw_memory_algorithms 201606L
1405+
#endif // _HAS_CXX23
1406+
13931407
#define __cpp_lib_experimental_erase_if 201411L
13941408
#define __cpp_lib_experimental_filesystem 201406L
13951409

tests/std/test.lst

+8
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,14 @@ tests\P1951R1_default_arguments_pair_forward_ctor
452452
tests\P2136R3_invoke_r
453453
tests\P2162R2_std_visit_for_derived_classes_from_variant
454454
tests\P2231R1_complete_constexpr_optional_variant
455+
tests\P2283R2_constexpr_uninitialized_copy
456+
tests\P2283R2_constexpr_uninitialized_copy_n
457+
tests\P2283R2_constexpr_uninitialized_fill
458+
tests\P2283R2_constexpr_uninitialized_fill_n
459+
tests\P2283R2_constexpr_uninitialized_move
460+
tests\P2283R2_constexpr_uninitialized_move_n
461+
tests\P2283R2_constexpr_uninitialized_value_construct
462+
tests\P2283R2_constexpr_uninitialized_value_construct_n
455463
tests\P2401R0_conditional_noexcept_for_exchange
456464
tests\P2415R2_owning_view
457465
tests\VSO_0000000_allocator_propagation
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_latest_matrix.lst

0 commit comments

Comments
 (0)