From f0f2f94d96cf46e2c8b976d1b76445296da05c46 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Sat, 30 May 2020 08:40:51 +0200 Subject: [PATCH 1/8] [xutility] Modernize _Ptr_meow_cat to use variable templates --- stl/inc/algorithm | 2 +- stl/inc/memory | 6 +- stl/inc/vector | 4 +- stl/inc/xmemory | 22 +-- stl/inc/xutility | 178 +++++++++++-------- tests/std/tests/VSO_0180469_ptr_cat/test.cpp | 19 +- 6 files changed, 134 insertions(+), 97 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 4e431bb53a..94a6f455cf 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1899,7 +1899,7 @@ namespace ranges { template requires indirectly_movable<_It1, _It2> _NODISCARD constexpr _It2 _Move_backward_common(const _It1 _First, _It1 _Last, _It2 _Result) { - if constexpr (_Ptr_move_cat<_It1, _It2>::_Trivially_copyable) { + if constexpr (_Can_memmove<_It1, _It2>) { if (!_STD is_constant_evaluated()) { return _Copy_backward_memmove(_First, _Last, _Result); } diff --git a/stl/inc/memory b/stl/inc/memory index 67b1cc410d..a79710a762 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -35,7 +35,7 @@ _NoThrowFwdIt uninitialized_copy_n(const _InIt _First, const _Diff _Count_raw, _ if (0 < _Count) { auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Ptr_copy_cat::_Really_trivial) { + if constexpr (_Can_memcpy_uninitialized) { _UDest = _Copy_memmove(_UFirst, _UFirst + _Count, _UDest); } else { _Uninitialized_backout _Backout{_UDest}; @@ -77,7 +77,7 @@ _NoThrowFwdIt uninitialized_copy_n(const _InIt _First, const _Diff _Count_raw, _ auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); _Seek_wrapped(_Dest, _Uninitialized_copy_n_unchecked2(_UFirst, _Count, _UDest, - bool_constant<_Ptr_copy_cat::_Really_trivial>{})); + bool_constant<_Can_memcpy_uninitialized>{})); } return _Dest; @@ -105,7 +105,7 @@ pair<_InIt, _NoThrowFwdIt> uninitialized_move_n(_InIt _First, const _Diff _Count if (0 < _Count) { auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Ptr_move_cat::_Really_trivial) { + if constexpr (_Can_memmove_uninitialized) { _UDest = _Copy_memmove(_UFirst, _UFirst + _Count, _UDest); _UFirst += _Count; } else { diff --git a/stl/inc/vector b/stl/inc/vector index 5a18de75a3..4b1a7637d6 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -629,7 +629,7 @@ private: const auto _Oldcapacity = static_cast(_My_data._Myend - _Myfirst); #if _HAS_IF_CONSTEXPR - if constexpr (conjunction_v::_Trivially_copyable>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alty, _Ty*, _Ty>, _Uses_default_destroy<_Alty, _Ty*>>) { if (_Newsize > _Oldcapacity) { _Clear_and_reserve_geometric(_Newsize); @@ -1101,7 +1101,7 @@ private: _My_data._Orphan_all(); #if _HAS_IF_CONSTEXPR - if constexpr (conjunction_v::_Trivially_copyable>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alty, _Ty*, decltype(*_First)>, _Uses_default_destroy<_Alty, _Ty*>>) { const auto _Oldcapacity = static_cast(_Myend - _Myfirst); diff --git a/stl/inc/xmemory b/stl/inc/xmemory index abb94ba7ac..40efd96c63 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1442,7 +1442,7 @@ struct _Uninitialized_backout { // struct to undo partially constructed ranges i template _NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // move [_First, _Last) to raw [_Dest, ...) - if constexpr (_Ptr_move_cat<_InIt, _NoThrowFwdIt>::_Really_trivial) { + if constexpr (_Can_memmove_uninitialized<_InIt, _NoThrowFwdIt>) { return _Copy_memmove(_First, _Last, _Dest); } else { _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; @@ -1476,7 +1476,7 @@ template _NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // move [_First, _Last) to raw [_Dest, ...), choose optimization return _Uninitialized_move_unchecked1( - _First, _Last, _Dest, bool_constant<_Ptr_move_cat<_InIt, _NoThrowFwdIt>::_Really_trivial>{}); + _First, _Last, _Dest, bool_constant<_Can_memmove_uninitialized<_InIt, _NoThrowFwdIt>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -1524,7 +1524,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy( auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (conjunction_v::_Really_trivial>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>) { _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); _Dest += _ULast - _UFirst; @@ -1572,7 +1572,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy( using _Ptrval = typename _Alloc::value_type*; return _Uninitialized_copy_al_unchecked(_UFirst, _ULast, _Dest, _Al, - bool_constant::_Really_trivial>, + bool_constant>, _Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -1586,7 +1586,7 @@ _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrow auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast)); - if constexpr (_Ptr_copy_cat::_Really_trivial) { + if constexpr (_Can_memcpy_uninitialized) { _UDest = _Copy_memmove(_UFirst, _ULast, _UDest); } else { _Uninitialized_backout _Backout{_UDest}; @@ -1627,7 +1627,7 @@ _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrow const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast)); _Seek_wrapped(_Dest, _Uninitialized_copy_unchecked(_UFirst, _ULast, _UDest, - bool_constant<_Ptr_copy_cat::_Really_trivial>{})); + bool_constant<_Can_memcpy_uninitialized>{})); return _Dest; } #endif // _HAS_IF_CONSTEXPR @@ -1642,7 +1642,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_move( using _Ptrval = typename _Alloc::value_type*; auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (conjunction_v::_Really_trivial>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>>) { _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); return _Dest + (_ULast - _UFirst); @@ -1689,10 +1689,10 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_move( // clang-format on using _Ptrval = typename _Alloc::value_type*; - _Seek_wrapped( - _Dest, _Uninitialized_move_al_unchecked(_UFirst, _ULast, _UDest, _Al, - bool_constant < _Ptr_move_cat::_Really_trivial - && _Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>::value > {})); + _Seek_wrapped(_Dest, + _Uninitialized_move_al_unchecked(_UFirst, _ULast, _UDest, _Al, + bool_constant < _Can_memmove_uninitialized && _Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>::value > {})); return _Dest; } #endif // _HAS_IF_CONSTEXPR diff --git a/stl/inc/xutility b/stl/inc/xutility index 9c82bb27c5..bfb1822080 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4256,69 +4256,111 @@ inline constexpr unreachable_sentinel_t unreachable_sentinel{}; #endif // __cpp_lib_concepts // FUNCTION TEMPLATE copy -template -struct _Ptr_cat_helper { - using _USource = _Unwrap_enum_t<_Source>; - using _UDest = _Unwrap_enum_t<_Dest>; - static constexpr bool _Really_trivial = conjunction_v< - bool_constant == is_same_v>, - is_integral<_USource>, is_integral<_UDest>>; - static constexpr bool _Trivially_copyable = _Really_trivial; -}; +// _Iterators_are_contiguous<_Iter1, _Iter2> reports whether both iterators are known to be contiguous. +// (Without concepts, this detection is limited, which will limit when we can activate certain optimizations.) +#ifdef __cpp_lib_concepts +// When concepts are available, we can detect arbitrary contiguous iterators. +template +_INLINE_VAR constexpr bool _Iterators_are_contiguous = contiguous_iterator<_Iter1> // + && contiguous_iterator<_Iter2>; +#else // ^^^ defined(__cpp_lib_concepts) ^^^ / vvv !defined(__cpp_lib_concepts) vvv +// When concepts aren't available, we can detect pointers. (Iterators should be unwrapped before using this.) +template +_INLINE_VAR constexpr bool _Iterators_are_contiguous = conjunction_v, is_pointer<_Iter2>>; +#endif // ^^^ !defined(__cpp_lib_concepts) ^^^ -template -struct _Ptr_cat_helper<_Elem, _Elem> { // determines _Ptr_cat's result when the types are the same - static constexpr bool _Really_trivial = is_trivial_v<_Elem>; - static constexpr bool _Trivially_copyable = is_trivially_copyable_v<_Elem>; +// VARIABLE TEMPLATE _Can_memop +enum class _Memop_cat { + _Copy, + _Copy_uninitialized, + _Move, + _Move_uninitialized, }; -template -struct _Ptr_cat_helper<_Anything*, const _Anything*> { - // determines _Ptr_cat's result when all we do is add const to a pointer - static constexpr bool _Really_trivial = true; - static constexpr bool _Trivially_copyable = true; -}; +// Integral types are eligible for memcpy in very specific cases. +// * Enumerations are treated as their underlying integral type +// * They must be the same size. (`int == long` is eligible; `int != long long` isn't.) +// * They are either both bool or both non bool +template +struct _Same_size_integral_or_bool + : bool_constant == is_same_v> {}; -template -struct _Ptr_cat_helper<_Anything*, volatile _Anything*> { - // determines _Ptr_cat's result when all we do is add volatile to a pointer - static constexpr bool _Really_trivial = true; - static constexpr bool _Trivially_copyable = true; -}; +template +_INLINE_VAR constexpr bool _Can_memop_integrals = + conjunction_v, is_integral<_Dest>, _Same_size_integral_or_bool<_Source, _Dest>>; -template -struct _Ptr_cat_helper<_Anything*, const volatile _Anything*> { - // determines _Ptr_cat's result when all we do is add cv to a pointer - static constexpr bool _Really_trivial = true; - static constexpr bool _Trivially_copyable = true; -}; +// Matching integer type are eligible for memcpy +template , _Unwrap_enum_t<_Dest>>> +_INLINE_VAR constexpr bool _Can_memop_elements = _Result; -struct _False_copy_cat { - static constexpr bool _Really_trivial = false; - static constexpr bool _Trivially_copyable = false; -}; +// Pointer elements are eligible for memcpy when they point to the same type, ignoring cv-qualification. +// This handles pointers to object types, pointers to void, and pointers to function types. +// Performance note: This doesn't attempt to handle `object* != void*`. +template +_INLINE_VAR constexpr bool _Can_memop_elements<_Source*, _Dest*, _Cat, false> = + is_same_v, remove_cv_t<_Dest>>; -template -struct _Ptr_copy_cat : _False_copy_cat {}; // unwrap the pointer-like type and dispatch to _Ptr_cat_helper for copy +// Types are eligible for memcpy / memmove when they are trivially copyable. +template +_INLINE_VAR constexpr bool _Can_memop_elements<_Ty, enable_if_t, _Ty>, _Memop_cat::_Copy, false> = + is_trivially_copyable_v<_Ty>; -template -struct _Ptr_copy_cat<_Source*, _Dest*> - : conditional_t, - _Ptr_cat_helper, remove_cv_t<_Dest>>, _False_copy_cat> {}; +template +_INLINE_VAR constexpr bool _Can_memop_elements<_Ty, enable_if_t, _Ty>, _Memop_cat::_Move, false> = + is_trivially_copyable_v<_Ty>; -template -struct _Ptr_copy_cat, _Dest*> : _Ptr_copy_cat<_Source*, _Dest*> {}; +// Types are eligible for memcpy / memmove into uninitialized memory when they are trivial. +template +_INLINE_VAR constexpr bool + _Can_memop_elements<_Ty, enable_if_t, _Ty>, _Memop_cat::_Copy_uninitialized, false> = + is_trivial_v<_Ty>; -template -struct _Ptr_move_cat : _False_copy_cat {}; // unwrap the pointer-like type and dispatch to _Ptr_cat_helper for move +template +_INLINE_VAR constexpr bool + _Can_memop_elements<_Ty, enable_if_t, _Ty>, _Memop_cat::_Move_uninitialized, false> = + is_trivial_v<_Ty>; + +// Different types are eligible for memcpy when they are trivially copy assignable. +template +_INLINE_VAR constexpr bool _Can_assign_elements = is_trivially_assignable_v<_Dest&, _Source&>; +// Different types are eligible for memmove when they are trivially move assignable. template -struct _Ptr_move_cat<_Source*, _Dest*> - : conditional_t, - _Ptr_cat_helper, remove_cv_t<_Dest>>, _False_copy_cat> {}; +_INLINE_VAR constexpr bool _Can_assign_elements<_Source, _Dest, _Memop_cat::_Move> = + is_trivially_assignable_v<_Dest&, _Source&&>; template -struct _Ptr_move_cat, _Dest*> : _Ptr_move_cat<_Source*, _Dest*> {}; +_INLINE_VAR constexpr bool _Can_assign_elements<_Source, _Dest, _Memop_cat::_Move_uninitialized> = + is_trivially_assignable_v<_Dest&, _Source&&>; + +// _Can_memop<_IterSource, _IterDest> reports whether we can activate the memory operation for +// arbitrary iterators. It ignores top-level constness on the source iterators and on the source elements. +template +_INLINE_VAR constexpr bool _Can_memop = false; + +template +_INLINE_VAR constexpr bool _Can_memop<_Source*, _Dest*, _Cat> = + conjunction_v>, + bool_constant<_Can_memop_elements, remove_volatile_t<_Dest>, _Cat>>>; + +template +_INLINE_VAR constexpr bool _Can_memop, _IterDest, _Cat> = + _Can_memop<_IterSource, _IterDest, _Cat>; + +template +_INLINE_VAR constexpr bool _Can_memcpy = _Can_memop, _IterDest, _Memop_cat::_Copy>; + +template +_INLINE_VAR constexpr bool _Can_memcpy_uninitialized = + _Can_memop, _IterDest, _Memop_cat::_Copy_uninitialized>; + +template +_INLINE_VAR constexpr bool _Can_memmove = _Can_memop, _IterDest, _Memop_cat::_Move>; + +template +_INLINE_VAR constexpr bool _Can_memmove_uninitialized = + _Can_memop, _IterDest, _Memop_cat::_Move_uninitialized>; template _OutIt _Copy_memmove(_InIt _First, _InIt _Last, _OutIt _Dest) { @@ -4344,7 +4386,7 @@ template _CONSTEXPR20 _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) // note: _Copy_unchecked has callers other than the copy family - if constexpr (_Ptr_copy_cat<_InIt, _OutIt>::_Trivially_copyable) { + if constexpr (_Can_memcpy<_InIt, _OutIt>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4380,7 +4422,7 @@ template _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) // note: _Copy_unchecked has callers other than the copy family - return _Copy_unchecked1(_First, _Last, _Dest, bool_constant<_Ptr_copy_cat<_InIt, _OutIt>::_Trivially_copyable>{}); + return _Copy_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memcpy<_InIt, _OutIt>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -4414,7 +4456,7 @@ _CONSTEXPR20 _OutIt copy_n(_InIt _First, _Diff _Count_raw, _OutIt _Dest) { if (0 < _Count) { auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Ptr_copy_cat::_Trivially_copyable) { + if constexpr (_Can_memcpy) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4474,9 +4516,8 @@ _OutIt copy_n(_InIt _First, _Diff _Count_raw, _OutIt _Dest) { // copy [_First, _ if (0 < _Count) { auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); - _Seek_wrapped( - _Dest, _Copy_n_unchecked4(_UFirst, _Count, _UDest, - bool_constant<_Ptr_copy_cat::_Trivially_copyable>{})); + _Seek_wrapped(_Dest, _Copy_n_unchecked4(_UFirst, _Count, _UDest, + bool_constant<_Can_memcpy>{})); } return _Dest; @@ -4514,7 +4555,7 @@ _BidIt2 _Copy_backward_memmove(move_iterator<_BidIt1> _First, move_iterator<_Bid template _NODISCARD _CONSTEXPR20 _BidIt2 _Copy_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // copy [_First, _Last) backwards to [..., _Dest) - if constexpr (_Ptr_copy_cat<_BidIt1, _BidIt2>::_Trivially_copyable) { + if constexpr (_Can_memcpy<_BidIt1, _BidIt2>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4564,7 +4605,7 @@ _BidIt2 copy_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // copy [_ const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, -_Idl_distance<_BidIt1>(_UFirst, _ULast)); _Seek_wrapped(_Dest, _Copy_backward_unchecked(_UFirst, _ULast, _UDest, - bool_constant<_Ptr_copy_cat::_Trivially_copyable>{})); + bool_constant<_Can_memcpy>{})); return _Dest; } #endif // _HAS_IF_CONSTEXPR @@ -4584,7 +4625,7 @@ template _CONSTEXPR20 _OutIt _Move_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // move [_First, _Last) to [_Dest, ...) // note: _Move_unchecked has callers other than the move family - if constexpr (_Ptr_move_cat<_InIt, _OutIt>::_Trivially_copyable) { + if constexpr (_Can_memmove<_InIt, _OutIt>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4620,7 +4661,7 @@ template _OutIt _Move_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // move [_First, _Last) to [_Dest, ...), choose optimization // note: _Move_unchecked has callers other than the move family - return _Move_unchecked1(_First, _Last, _Dest, bool_constant<_Ptr_move_cat<_InIt, _OutIt>::_Trivially_copyable>{}); + return _Move_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memmove<_InIt, _OutIt>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -4652,7 +4693,7 @@ template _CONSTEXPR20 _BidIt2 _Move_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // move [_First, _Last) backwards to [..., _Dest) // note: _Move_backward_unchecked has callers other than the move_backward family - if constexpr (_Ptr_move_cat<_BidIt1, _BidIt2>::_Trivially_copyable) { + if constexpr (_Can_memmove<_BidIt1, _BidIt2>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4688,8 +4729,7 @@ template _BidIt2 _Move_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // move [_First, _Last) backwards to [..., _Dest), choose optimization // note: _Move_backward_unchecked has callers other than the move_backward family - return _Move_backward_unchecked1( - _First, _Last, _Dest, bool_constant<_Ptr_move_cat<_BidIt1, _BidIt2>::_Trivially_copyable>{}); + return _Move_backward_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memmove<_BidIt1, _BidIt2>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -4948,20 +4988,6 @@ template _INLINE_VAR constexpr bool _Can_memcmp_elements_with_pred = _Can_memcmp_elements<_Elem1, _Elem2> // && _Pred_is_consistent_with_memcmp<_Elem1, _Elem2, _Pr>; -// _Iterators_are_contiguous<_Iter1, _Iter2> reports whether both iterators are known to be contiguous. -// (Without concepts, this detection is limited, which will limit when we can activate the memcmp optimization.) - -#ifdef __cpp_lib_concepts -// When concepts are available, we can detect arbitrary contiguous iterators. -template -_INLINE_VAR constexpr bool _Iterators_are_contiguous = contiguous_iterator<_Iter1> // - && contiguous_iterator<_Iter2>; -#else // ^^^ defined(__cpp_lib_concepts) ^^^ / vvv !defined(__cpp_lib_concepts) vvv -// When concepts aren't available, we can detect pointers. (Iterators should be unwrapped before using this.) -template -_INLINE_VAR constexpr bool _Iterators_are_contiguous = conjunction_v, is_pointer<_Iter2>>; -#endif // ^^^ !defined(__cpp_lib_concepts) ^^^ - // _Equal_memcmp_is_safe<_Iter1, _Iter2, _Pr> reports whether we can activate the memcmp optimization // for arbitrary iterators and predicates. // It ignores top-level constness on the iterators and on the elements. diff --git a/tests/std/tests/VSO_0180469_ptr_cat/test.cpp b/tests/std/tests/VSO_0180469_ptr_cat/test.cpp index e0747b48ca..d7631effdb 100644 --- a/tests/std/tests/VSO_0180469_ptr_cat/test.cpp +++ b/tests/std/tests/VSO_0180469_ptr_cat/test.cpp @@ -31,13 +31,13 @@ void assert_same() { template struct test_ptr_cat_helper { - static constexpr bool CopyReallyTrivial = _Ptr_copy_cat::_Really_trivial; - static constexpr bool CopyTriviallyCopyable = _Ptr_copy_cat::_Trivially_copyable; + static constexpr bool CopyReallyTrivial = _Can_memcpy_uninitialized; + static constexpr bool CopyTriviallyCopyable = _Can_memcpy; STATIC_ASSERT(Expected == CopyReallyTrivial + CopyTriviallyCopyable); STATIC_ASSERT(!CopyReallyTrivial || CopyTriviallyCopyable); - static constexpr bool MoveReallyTrivial = _Ptr_move_cat::_Really_trivial; - static constexpr bool MoveTriviallyCopyable = _Ptr_move_cat::_Trivially_copyable; + static constexpr bool MoveReallyTrivial = _Can_memmove_uninitialized; + static constexpr bool MoveTriviallyCopyable = _Can_memmove; STATIC_ASSERT(Expected == MoveReallyTrivial + MoveTriviallyCopyable); STATIC_ASSERT(!MoveReallyTrivial || MoveTriviallyCopyable); }; @@ -186,6 +186,17 @@ void ptr_cat_test_cases() { test_ptr_cat<2, volatile int*, const volatile int*>(); test_ptr_cat<2, const volatile int*, const volatile int*>(); + // Pointer to pointer should work + test_ptr_cat<2, int**, int**>(); + test_ptr_cat<2, pod_struct**, pod_struct**>(); + test_ptr_cat<2, trivially_copyable_struct**, trivially_copyable_struct**>(); + test_ptr_cat<2, custom_copy_struct**, custom_copy_struct**>(); + + // Pointer to pointer of different types should not work + test_ptr_cat<0, int**, pod_struct**>(); + test_ptr_cat<0, pod_struct**, trivially_copyable_struct**>(); + test_ptr_cat<0, trivially_copyable_struct**, custom_copy_struct**>(); + // Pointers to derived are implicitly convertible to pointers to base, but there // may still be code required to change an offset, so we don't want to memmove them test_ptr_cat<0, derived_class, base_class>(); From 31d6645567b474ae63ea00ca6d235451fe9aa29e Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Wed, 7 Oct 2020 12:15:59 +0200 Subject: [PATCH 2/8] Use better names --- stl/inc/algorithm | 2 +- stl/inc/memory | 14 +++++----- stl/inc/vector | 4 +-- stl/inc/xmemory | 16 +++++------ stl/inc/xutility | 28 ++++++++++---------- tests/std/tests/VSO_0180469_ptr_cat/test.cpp | 8 +++--- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 0c71f4ce52..89b5780eb7 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1850,7 +1850,7 @@ namespace ranges { template requires indirectly_movable<_It1, _It2> _NODISCARD constexpr _It2 _Move_backward_common(const _It1 _First, _It1 _Last, _It2 _Result) { - if constexpr (_Can_memmove<_It1, _It2>) { + if constexpr (_Can_memmove_in_move<_It1, _It2>) { if (!_STD is_constant_evaluated()) { return _Copy_backward_memmove(_First, _Last, _Result); } diff --git a/stl/inc/memory b/stl/inc/memory index 8e40885285..04305704ed 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -107,7 +107,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(_No_throw_sentinel_for<_OSe, _Out>); _STL_INTERNAL_STATIC_ASSERT(constructible_from, iter_reference_t<_It>>); - if constexpr (is_same_v<_Se, _It> && _Can_memcpy_uninitialized<_It, _Out>) { + if constexpr (is_same_v<_Se, _It> && _Can_memmove_in_uninitialized_copy<_It, _Out>) { return _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -137,7 +137,7 @@ _NoThrowFwdIt uninitialized_copy_n(const _InIt _First, const _Diff _Count_raw, _ auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Can_memcpy_uninitialized) { + if constexpr (_Can_memmove_in_uninitialized_copy) { _UDest = _Copy_memmove(_UFirst, _UFirst + _Count, _UDest); } else { _Uninitialized_backout _Backout{_UDest}; @@ -182,7 +182,7 @@ _NoThrowFwdIt uninitialized_copy_n(const _InIt _First, const _Diff _Count_raw, _ auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); _Seek_wrapped(_Dest, _Uninitialized_copy_n_unchecked2(_UFirst, _Count, _UDest, - bool_constant<_Can_memcpy_uninitialized>{})); + bool_constant<_Can_memmove_in_uninitialized_copy>{})); return _Dest; } #endif // _HAS_IF_CONSTEXPR @@ -212,7 +212,7 @@ namespace ranges { auto _IFirst = _Get_unwrapped_n(_STD move(_First1), _Count); auto _OFirst = _Get_unwrapped(_STD move(_First2)); const auto _OLast = _Get_unwrapped(_STD move(_Last2)); - if constexpr (_Can_memcpy_uninitialized<_It, _Out>) { + if constexpr (_Can_memmove_in_uninitialized_copy<_It, _Out>) { _OFirst = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -299,7 +299,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(_No_throw_sentinel_for<_OSe, _Out>); _STL_INTERNAL_STATIC_ASSERT(constructible_from, iter_rvalue_reference_t<_It>>); - if constexpr (is_same_v<_Se, _It> && _Can_memmove_uninitialized<_It, _Out>) { + if constexpr (is_same_v<_Se, _It> && _Can_memmove_in_uninitialized_move<_It, _Out>) { return _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -328,7 +328,7 @@ pair<_InIt, _NoThrowFwdIt> uninitialized_move_n(_InIt _First, const _Diff _Count auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Can_memmove_uninitialized) { + if constexpr (_Can_memmove_in_uninitialized_move) { _UDest = _Copy_memmove(_UFirst, _UFirst + _Count, _UDest); _UFirst += _Count; } else { @@ -373,7 +373,7 @@ namespace ranges { auto _IFirst = _Get_unwrapped_n(_STD move(_First1), _Count); auto _OFirst = _Get_unwrapped(_STD move(_First2)); const auto _OLast = _Get_unwrapped(_STD move(_Last2)); - if constexpr (_Can_memmove_uninitialized<_It, _Out>) { + if constexpr (_Can_memmove_in_uninitialized_move<_It, _Out>) { _OFirst = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; diff --git a/stl/inc/vector b/stl/inc/vector index 01d7aee538..6a72a54a1c 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -636,7 +636,7 @@ private: const auto _Oldcapacity = static_cast(_My_data._Myend - _Myfirst); #if _HAS_IF_CONSTEXPR - if constexpr (conjunction_v>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alty, _Ty*, _Ty>, _Uses_default_destroy<_Alty, _Ty*>>) { if (_Newsize > _Oldcapacity) { _Clear_and_reserve_geometric(_Newsize); @@ -1108,7 +1108,7 @@ private: _My_data._Orphan_all(); #if _HAS_IF_CONSTEXPR - if constexpr (conjunction_v>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alty, _Ty*, decltype(*_First)>, _Uses_default_destroy<_Alty, _Ty*>>) { const auto _Oldcapacity = static_cast(_Myend - _Myfirst); diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 41a0fffba7..eb0604b81b 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1480,7 +1480,7 @@ namespace ranges { template _NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // move [_First, _Last) to raw [_Dest, ...) - if constexpr (_Can_memmove_uninitialized<_InIt, _NoThrowFwdIt>) { + if constexpr (_Can_memmove_in_uninitialized_move<_InIt, _NoThrowFwdIt>) { return _Copy_memmove(_First, _Last, _Dest); } else { _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; @@ -1514,7 +1514,7 @@ template _NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // move [_First, _Last) to raw [_Dest, ...), choose optimization return _Uninitialized_move_unchecked1( - _First, _Last, _Dest, bool_constant<_Can_memmove_uninitialized<_InIt, _NoThrowFwdIt>>{}); + _First, _Last, _Dest, bool_constant<_Can_memmove_in_uninitialized_move<_InIt, _NoThrowFwdIt>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -1562,7 +1562,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy( auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (conjunction_v>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>) { _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); _Dest += _ULast - _UFirst; @@ -1610,7 +1610,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy( using _Ptrval = typename _Alloc::value_type*; return _Uninitialized_copy_al_unchecked(_UFirst, _ULast, _Dest, _Al, - bool_constant>, + bool_constant>, _Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -1624,7 +1624,7 @@ _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrow auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast)); - if constexpr (_Can_memcpy_uninitialized) { + if constexpr (_Can_memmove_in_uninitialized_copy) { _UDest = _Copy_memmove(_UFirst, _ULast, _UDest); } else { _Uninitialized_backout _Backout{_UDest}; @@ -1665,7 +1665,7 @@ _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrow const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast)); _Seek_wrapped(_Dest, _Uninitialized_copy_unchecked(_UFirst, _ULast, _UDest, - bool_constant<_Can_memcpy_uninitialized>{})); + bool_constant<_Can_memmove_in_uninitialized_copy>{})); return _Dest; } #endif // _HAS_IF_CONSTEXPR @@ -1680,7 +1680,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_move( using _Ptrval = typename _Alloc::value_type*; auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (conjunction_v>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>>) { _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); return _Dest + (_ULast - _UFirst); @@ -1729,7 +1729,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_move( using _Ptrval = typename _Alloc::value_type*; _Seek_wrapped(_Dest, _Uninitialized_move_al_unchecked(_UFirst, _ULast, _UDest, _Al, - bool_constant < _Can_memmove_uninitialized && _Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>::value > {})); return _Dest; } diff --git a/stl/inc/xutility b/stl/inc/xutility index b4ae2546c4..1389dc339d 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4392,17 +4392,17 @@ _INLINE_VAR constexpr bool _Can_memop, _IterDest, _Ca _Can_memop<_IterSource, _IterDest, _Cat>; template -_INLINE_VAR constexpr bool _Can_memcpy = _Can_memop, _IterDest, _Memop_cat::_Copy>; +_INLINE_VAR constexpr bool _Can_memmove_in_copy = _Can_memop, _IterDest, _Memop_cat::_Copy>; template -_INLINE_VAR constexpr bool _Can_memcpy_uninitialized = +_INLINE_VAR constexpr bool _Can_memmove_in_uninitialized_copy = _Can_memop, _IterDest, _Memop_cat::_Copy_uninitialized>; template -_INLINE_VAR constexpr bool _Can_memmove = _Can_memop, _IterDest, _Memop_cat::_Move>; +_INLINE_VAR constexpr bool _Can_memmove_in_move = _Can_memop, _IterDest, _Memop_cat::_Move>; template -_INLINE_VAR constexpr bool _Can_memmove_uninitialized = +_INLINE_VAR constexpr bool _Can_memmove_in_uninitialized_move = _Can_memop, _IterDest, _Memop_cat::_Move_uninitialized>; template @@ -4440,7 +4440,7 @@ template _CONSTEXPR20 _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) // note: _Copy_unchecked has callers other than the copy family - if constexpr (_Can_memcpy<_InIt, _OutIt>) { + if constexpr (_Can_memmove_in_copy<_InIt, _OutIt>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4476,7 +4476,7 @@ template _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) // note: _Copy_unchecked has callers other than the copy family - return _Copy_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memcpy<_InIt, _OutIt>>{}); + return _Copy_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memmove_in_copy<_InIt, _OutIt>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -4510,7 +4510,7 @@ _CONSTEXPR20 _OutIt copy_n(_InIt _First, _Diff _Count_raw, _OutIt _Dest) { if (0 < _Count) { auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Can_memcpy) { + if constexpr (_Can_memmove_in_copy) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4571,7 +4571,7 @@ _OutIt copy_n(_InIt _First, _Diff _Count_raw, _OutIt _Dest) { // copy [_First, _ auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); _Seek_wrapped(_Dest, _Copy_n_unchecked4(_UFirst, _Count, _UDest, - bool_constant<_Can_memcpy>{})); + bool_constant<_Can_memmove_in_copy>{})); } return _Dest; @@ -4609,7 +4609,7 @@ _BidIt2 _Copy_backward_memmove(move_iterator<_BidIt1> _First, move_iterator<_Bid template _NODISCARD _CONSTEXPR20 _BidIt2 _Copy_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // copy [_First, _Last) backwards to [..., _Dest) - if constexpr (_Can_memcpy<_BidIt1, _BidIt2>) { + if constexpr (_Can_memmove_in_copy<_BidIt1, _BidIt2>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4659,7 +4659,7 @@ _BidIt2 copy_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // copy [_ const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, -_Idl_distance<_BidIt1>(_UFirst, _ULast)); _Seek_wrapped(_Dest, _Copy_backward_unchecked(_UFirst, _ULast, _UDest, - bool_constant<_Can_memcpy>{})); + bool_constant<_Can_memmove_in_copy>{})); return _Dest; } #endif // _HAS_IF_CONSTEXPR @@ -4679,7 +4679,7 @@ template _CONSTEXPR20 _OutIt _Move_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // move [_First, _Last) to [_Dest, ...) // note: _Move_unchecked has callers other than the move family - if constexpr (_Can_memmove<_InIt, _OutIt>) { + if constexpr (_Can_memmove_in_move<_InIt, _OutIt>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4715,7 +4715,7 @@ template _OutIt _Move_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // move [_First, _Last) to [_Dest, ...), choose optimization // note: _Move_unchecked has callers other than the move family - return _Move_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memmove<_InIt, _OutIt>>{}); + return _Move_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memmove_in_move<_InIt, _OutIt>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -4747,7 +4747,7 @@ template _CONSTEXPR20 _BidIt2 _Move_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // move [_First, _Last) backwards to [..., _Dest) // note: _Move_backward_unchecked has callers other than the move_backward family - if constexpr (_Can_memmove<_BidIt1, _BidIt2>) { + if constexpr (_Can_memmove_in_move<_BidIt1, _BidIt2>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4783,7 +4783,7 @@ template _BidIt2 _Move_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // move [_First, _Last) backwards to [..., _Dest), choose optimization // note: _Move_backward_unchecked has callers other than the move_backward family - return _Move_backward_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memmove<_BidIt1, _BidIt2>>{}); + return _Move_backward_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memmove_in_move<_BidIt1, _BidIt2>>{}); } #endif // _HAS_IF_CONSTEXPR diff --git a/tests/std/tests/VSO_0180469_ptr_cat/test.cpp b/tests/std/tests/VSO_0180469_ptr_cat/test.cpp index 6c480e063f..a276c05ea1 100644 --- a/tests/std/tests/VSO_0180469_ptr_cat/test.cpp +++ b/tests/std/tests/VSO_0180469_ptr_cat/test.cpp @@ -31,13 +31,13 @@ void assert_same() { template struct test_ptr_cat_helper { - static constexpr bool CopyReallyTrivial = _Can_memcpy_uninitialized; - static constexpr bool CopyTriviallyCopyable = _Can_memcpy; + static constexpr bool CopyReallyTrivial = _Can_memmove_in_uninitialized_copy; + static constexpr bool CopyTriviallyCopyable = _Can_memmove_in_copy; STATIC_ASSERT(Expected == CopyReallyTrivial + CopyTriviallyCopyable); STATIC_ASSERT(!CopyReallyTrivial || CopyTriviallyCopyable); - static constexpr bool MoveReallyTrivial = _Can_memmove_uninitialized; - static constexpr bool MoveTriviallyCopyable = _Can_memmove; + static constexpr bool MoveReallyTrivial = _Can_memmove_in_uninitialized_move; + static constexpr bool MoveTriviallyCopyable = _Can_memmove_in_move; STATIC_ASSERT(Expected == MoveReallyTrivial + MoveTriviallyCopyable); STATIC_ASSERT(!MoveReallyTrivial || MoveTriviallyCopyable); }; From c6fbaec1559758982545ec43964847532ce2b21d Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Wed, 7 Oct 2020 12:18:55 +0200 Subject: [PATCH 3/8] Use the same pattern for _Fill_memset_is_safe and _Equal_memcmp_is_safe --- stl/inc/algorithm | 12 +- stl/inc/memory | 12 +- stl/inc/xmemory | 8 +- stl/inc/xutility | 24 ++-- tests/std/tests/VSO_0180469_ptr_cat/test.cpp | 121 +++++++++---------- 5 files changed, 88 insertions(+), 89 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 89b5780eb7..895f5813b4 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -2217,7 +2217,7 @@ namespace ranges { template _NODISCARD _CONSTEXPR20 bool _Equal_rev_pred_unchecked(_InIt1 _First1, _InIt2 _First2, const _InIt2 _Last2, _Pr _Pred) { // compare [_First1, ...) to [_First2, _Last2) - if constexpr (_Equal_memcmp_is_safe<_InIt1, _InIt2, _Pr>) { + if constexpr (_Can_memcmp_in_equal<_InIt1, _InIt2, _Pr>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -2238,7 +2238,7 @@ _NODISCARD _CONSTEXPR20 bool _Equal_rev_pred_unchecked(_InIt1 _First1, _InIt2 _F return true; } #else // ^^^ _HAS_IF_CONSTEXPR ^^^ // vvv !_HAS_IF_CONSTEXPR vvv -template , int> = 0> +template , int> = 0> bool _Equal_rev_pred_unchecked(_InIt1 _First1, _InIt2 _First2, const _InIt2 _Last2, _Pr _Pred) { // compare [_First1, ...) to [_First2, _Last2), no special optimization for (; _First2 != _Last2; ++_First1, (void) ++_First2) { @@ -2250,7 +2250,7 @@ bool _Equal_rev_pred_unchecked(_InIt1 _First1, _InIt2 _First2, const _InIt2 _Las return true; } -template , int> = 0> +template , int> = 0> bool _Equal_rev_pred_unchecked(const _InIt1 _First1, const _InIt2 _First2, const _InIt2 _Last2, _Pr) { // compare [_First1, ...) to [_First2, _Last2), memcmp optimization const auto _First1_ch = reinterpret_cast(_First1); @@ -2391,7 +2391,7 @@ namespace ranges { // clang-format off template concept _Equal_rev_pred_can_memcmp = is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity> - && is_same_v<_Se2, _It2> && _Equal_memcmp_is_safe<_It1, _It2, _Pr>; + && is_same_v<_Se2, _It2> && _Can_memcmp_in_equal<_It1, _It2, _Pr>; template _Se2, class _Pr, class _Pj1, class _Pj2> requires indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2> @@ -3938,7 +3938,7 @@ namespace ranges { _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_STD move(_First)); const auto _ULast = _Get_unwrapped(_STD move(_Last)); - if constexpr (_Fill_memset_is_safe) { + if constexpr (_Can_memset_in_fill) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -3978,7 +3978,7 @@ namespace ranges { constexpr _It operator()(_It _First, iter_difference_t<_It> _Count, const _Ty& _Value) const { if (_Count > 0) { auto _UFirst = _Get_unwrapped_n(_STD move(_First), _Count); - if constexpr (_Fill_memset_is_safe) { + if constexpr (_Can_memset_in_fill) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated diff --git a/stl/inc/memory b/stl/inc/memory index 04305704ed..f77b03f06b 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -426,7 +426,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(_No_throw_sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(constructible_from, const _Ty&>); - if constexpr (_Fill_memset_is_safe<_It, _Ty>) { + if constexpr (_Can_memset_in_fill<_It, _Ty>) { const auto _OFinal = _RANGES next(_OFirst, _STD move(_OLast)); const auto _Diff = static_cast(_OFinal - _OFirst); _Fill_memset(_OFirst, _Val, _Diff); @@ -458,7 +458,7 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, } auto _UFirst = _Get_unwrapped_n(_First, _Count); - if constexpr (_Fill_memset_is_safe<_Unwrapped_n_t, _Tval>) { + if constexpr (_Can_memset_in_fill<_Unwrapped_n_t, _Tval>) { _Fill_memset(_UFirst, _Val, static_cast(_Count)); _UFirst += _Count; } else { @@ -505,7 +505,7 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, auto _UFirst = _Get_unwrapped_n(_STD move(_First), _Count); _Seek_wrapped(_First, _Uninitialized_fill_n_unchecked1(_STD move(_UFirst), _Count, _Val, - bool_constant<_Fill_memset_is_safe<_Unwrapped_t<_NoThrowFwdIt>, _Tval>>{})); + bool_constant<_Can_memset_in_fill<_Unwrapped_t<_NoThrowFwdIt>, _Tval>>{})); return _First; } #endif // _HAS_IF_CONSTEXPR @@ -527,7 +527,7 @@ namespace ranges { } auto _UFirst = _Get_unwrapped_n(_STD move(_First), _Count); - if constexpr (_Fill_memset_is_safe<_It, _Ty>) { + if constexpr (_Can_memset_in_fill<_It, _Ty>) { _Fill_memset(_UFirst, _Val, static_cast(_Count)); _Seek_wrapped(_First, _UFirst + _Count); } else { @@ -2359,7 +2359,7 @@ void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, _Uninitialized_copy_multidimensional(_Val, _Out[_Idx]); // intentionally copy, not fill } _Guard._Target = nullptr; - } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty>) { + } else if constexpr (_Can_memset_in_fill<_Ty*, _Ty>) { _Fill_memset(_Out, _Val, _Size); } else { _Uninitialized_rev_destroying_backout _Backout{_Out}; @@ -2682,7 +2682,7 @@ void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Si _Uninitialized_copy_multidimensional_al(_Val, _Out[_Idx], _Al); // intentionally copy, not fill } _Guard._Target = nullptr; - } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, const _Ty&>::value) { + } else if constexpr (_Can_memset_in_fill<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, const _Ty&>::value) { _Fill_memset(_Out, _Val, _Size); } else { _Uninitialized_rev_destroying_backout_al _Backout{_Out, _Al}; diff --git a/stl/inc/xmemory b/stl/inc/xmemory index eb0604b81b..eb6962bba0 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1742,7 +1742,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n( _Alloc_ptr_t<_Alloc> _First, _Alloc_size_t<_Alloc> _Count, const typename _Alloc::value_type& _Val, _Alloc& _Al) { // copy _Count copies of _Val to raw _First, using _Al using _Ty = typename _Alloc::value_type; - if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { + if constexpr (_Can_memset_in_fill<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { _Fill_memset(_Unfancy(_First), _Val, static_cast(_Count)); return _First + _Count; } else { @@ -1781,7 +1781,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n(_Alloc_ptr_t<_Alloc> _First, const _A // copy _Count copies of _Val to raw _First, using _Al using _Ty = typename _Alloc::value_type; return _Uninit_alloc_fill_n1(_First, _Count, _Val, _Al, - bool_constant < _Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value > {}); + bool_constant < _Can_memset_in_fill<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value > {}); } #endif // _HAS_IF_CONSTEXPR @@ -1793,7 +1793,7 @@ void uninitialized_fill(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, c _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (_Fill_memset_is_safe<_Unwrapped_t, _Tval>) { + if constexpr (_Can_memset_in_fill<_Unwrapped_t, _Tval>) { _Fill_memset(_UFirst, _Val, static_cast(_ULast - _UFirst)); } else { _Uninitialized_backout<_Unwrapped_t> _Backout{_UFirst}; @@ -1830,7 +1830,7 @@ void uninitialized_fill(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, c _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); _Uninitialized_fill_unchecked(_UFirst, _Get_unwrapped(_Last), _Val, - bool_constant<_Fill_memset_is_safe<_Unwrapped_t, _Tval>>{}); + bool_constant<_Can_memset_in_fill<_Unwrapped_t, _Tval>>{}); } #endif // _HAS_IF_CONSTEXPR diff --git a/stl/inc/xutility b/stl/inc/xutility index 1389dc339d..b0b8b76313 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4836,14 +4836,14 @@ struct _Is_character_or_byte_or_bool : true_type {}; template <> struct _Is_character_or_byte_or_bool : true_type {}; -// _Fill_memset_is_safe determines if _FwdIt and _Ty are eligible for memset optimization in fill +// _Can_memset_in_fill determines if _FwdIt and _Ty are eligible for memset optimization in fill template > -_INLINE_VAR constexpr bool _Fill_memset_is_safe = conjunction_v, +_INLINE_VAR constexpr bool _Can_memset_in_fill = conjunction_v, _Is_character_or_byte_or_bool<_Unwrap_enum_t>>>, is_assignable<_Iter_ref_t<_FwdIt>, const _Ty&>>; template -_INLINE_VAR constexpr bool _Fill_memset_is_safe<_FwdIt, _Ty, false> = false; +_INLINE_VAR constexpr bool _Can_memset_in_fill<_FwdIt, _Ty, false> = false; template void _Fill_memset(_DestTy* const _Dest, const _Ty _Val, const size_t _Count) { @@ -4861,7 +4861,7 @@ _CONSTEXPR20 void fill(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) } else { auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (_Fill_memset_is_safe) { + if constexpr (_Can_memset_in_fill) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4895,7 +4895,7 @@ template void fill(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { // copy _Val through [_First, _Last) _Adl_verify_range(_First, _Last); _Fill_unchecked1(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Val, - bool_constant<_Fill_memset_is_safe<_Unwrapped_t, _Ty>>{}); + bool_constant<_Can_memset_in_fill<_Unwrapped_t, _Ty>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -4922,7 +4922,7 @@ _CONSTEXPR20 _OutIt fill_n(_OutIt _Dest, const _Diff _Count_raw, const _Ty& _Val return _Last; } else { auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Fill_memset_is_safe) { + if constexpr (_Can_memset_in_fill) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4969,7 +4969,7 @@ _OutIt fill_n(_OutIt _Dest, const _Diff _Count_raw, const _Ty& _Val) { if (0 < _Count) { auto _UDest = _Get_unwrapped_n(_Dest, _Count); _Seek_wrapped(_Dest, - _Fill_n_unchecked2(_UDest, _Count, _Val, bool_constant<_Fill_memset_is_safe>{})); + _Fill_n_unchecked2(_UDest, _Count, _Val, bool_constant<_Can_memset_in_fill>{})); } return _Dest; @@ -5052,7 +5052,7 @@ template _INLINE_VAR constexpr bool _Can_memcmp_elements_with_pred = _Can_memcmp_elements<_Elem1, _Elem2> // && _Pred_is_consistent_with_memcmp<_Elem1, _Elem2, _Pr>; -// _Equal_memcmp_is_safe<_Iter1, _Iter2, _Pr> reports whether we can activate the memcmp optimization +// _Can_memcmp_in_equal<_Iter1, _Iter2, _Pr> reports whether we can activate the memcmp optimization // for arbitrary iterators and predicates. // It ignores top-level constness on the iterators and on the elements. template @@ -5061,7 +5061,7 @@ _INLINE_VAR constexpr bool _Equal_memcmp_is_safe_helper = _Iterators_are_contigu remove_const_t>>, _Pr>; template -_INLINE_VAR constexpr bool _Equal_memcmp_is_safe = +_INLINE_VAR constexpr bool _Can_memcmp_in_equal = _Equal_memcmp_is_safe_helper, remove_const_t<_Iter2>, _Pr>; #if _HAS_IF_CONSTEXPR @@ -5072,7 +5072,7 @@ _NODISCARD _CONSTEXPR20 bool equal(const _InIt1 _First1, const _InIt1 _Last1, co auto _UFirst1 = _Get_unwrapped(_First1); const auto _ULast1 = _Get_unwrapped(_Last1); auto _UFirst2 = _Get_unwrapped_n(_First2, _Idl_distance<_InIt1>(_UFirst1, _ULast1)); - if constexpr (_Equal_memcmp_is_safe) { + if constexpr (_Can_memcmp_in_equal) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -5093,7 +5093,7 @@ _NODISCARD _CONSTEXPR20 bool equal(const _InIt1 _First1, const _InIt1 _Last1, co return true; } #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv -template , int> = 0> +template , int> = 0> bool _Equal_unchecked(_InIt1 _First1, const _InIt1 _Last1, _InIt2 _First2, _Pr _Pred) { // compare [_First1, _Last1) to [_First2, ...), no special optimization for (; _First1 != _Last1; ++_First1, (void) ++_First2) { @@ -5105,7 +5105,7 @@ bool _Equal_unchecked(_InIt1 _First1, const _InIt1 _Last1, _InIt2 _First2, _Pr _ return true; } -template , int> = 0> +template , int> = 0> bool _Equal_unchecked(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _Pr) { // compare [_First1, _Last1) to [_First2, ...), memcmp optimization const auto _First1_ch = reinterpret_cast(_First1); diff --git a/tests/std/tests/VSO_0180469_ptr_cat/test.cpp b/tests/std/tests/VSO_0180469_ptr_cat/test.cpp index a276c05ea1..ed6ad8137c 100644 --- a/tests/std/tests/VSO_0180469_ptr_cat/test.cpp +++ b/tests/std/tests/VSO_0180469_ptr_cat/test.cpp @@ -234,105 +234,104 @@ void ptr_cat_test_cases() { template void test_case_Equal_memcmp_is_safe_comparator() { // Default case - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); // Adding const should not change the answer - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); // Top level const should not change the answer - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal == Expected); // Adding volatile anywhere should explode - STATIC_ASSERT(_Equal_memcmp_is_safe == false); - STATIC_ASSERT(_Equal_memcmp_is_safe == false); - STATIC_ASSERT(_Equal_memcmp_is_safe == false); - STATIC_ASSERT(_Equal_memcmp_is_safe == false); - STATIC_ASSERT(_Equal_memcmp_is_safe == false); - STATIC_ASSERT(_Equal_memcmp_is_safe == false); - STATIC_ASSERT(_Equal_memcmp_is_safe == false); - STATIC_ASSERT(_Equal_memcmp_is_safe == false); - STATIC_ASSERT(_Equal_memcmp_is_safe == false); - STATIC_ASSERT(_Equal_memcmp_is_safe == false); - STATIC_ASSERT(_Equal_memcmp_is_safe == false); - STATIC_ASSERT(_Equal_memcmp_is_safe == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); #ifdef __cpp_lib_concepts // contiguous iterators should not change the answer if constexpr (!is_same_v && !is_same_v) { // vector::iterator is not contiguous STATIC_ASSERT( - _Equal_memcmp_is_safe::iterator, typename vector::iterator, Pr> == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe::const_iterator, + _Can_memcmp_in_equal::iterator, typename vector::iterator, Pr> == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal::const_iterator, typename vector::const_iterator, Pr> == Expected); } STATIC_ASSERT( - _Equal_memcmp_is_safe::iterator, typename array::iterator, Pr> == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe::const_iterator, + _Can_memcmp_in_equal::iterator, typename array::iterator, Pr> == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal::const_iterator, typename array::const_iterator, Pr> == Expected); // Mixing contiguous iterators should not change the answer if constexpr (!is_same_v && !is_same_v) { - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, typename vector::const_iterator, + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename vector::const_iterator, Pr> == Expected); } if constexpr (!is_same_v) { - STATIC_ASSERT(_Equal_memcmp_is_safe::const_iterator, + STATIC_ASSERT(_Can_memcmp_in_equal::const_iterator, typename vector::const_iterator, Pr> == Expected); } if constexpr (!is_same_v) { - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, typename array::iterator, - Pr> == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, typename array::const_iterator, + STATIC_ASSERT( + _Can_memcmp_in_equal::iterator, typename array::iterator, Pr> == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename array::const_iterator, Pr> == Expected); } // span iterators are contiguous + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == Expected); STATIC_ASSERT( - _Equal_memcmp_is_safe::iterator, typename span::iterator, Pr> == Expected); - STATIC_ASSERT( - _Equal_memcmp_is_safe::iterator, typename span::iterator, Pr> == Expected); + _Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == Expected); STATIC_ASSERT( - _Equal_memcmp_is_safe::iterator, typename span::iterator, Pr> == Expected); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, typename span::iterator, + _Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == Expected); + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == Expected); // contiguous iterators to volatile should explode STATIC_ASSERT( - _Equal_memcmp_is_safe::iterator, typename span::iterator, Pr> == false); + _Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); STATIC_ASSERT( - _Equal_memcmp_is_safe::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, - typename span::iterator, Pr> == false); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, typename span::iterator, + _Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, + Pr> == false); + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, typename span::iterator, + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, typename span::iterator, + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, typename span::iterator, + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); #endif // __cpp_lib_concepts // Non-contiguous iterators should explode - STATIC_ASSERT(_Equal_memcmp_is_safe::iterator, typename list::iterator, Pr> == false); + STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename list::iterator, Pr> == false); } template @@ -344,15 +343,15 @@ void test_case_Equal_memcmp_is_safe() { #endif // __cpp_lib_concepts // equal_to< some other T > should explode - STATIC_ASSERT(_Equal_memcmp_is_safe>> == false); + STATIC_ASSERT(_Can_memcmp_in_equal>> == false); // Non equal_to comparison functions should explode auto lambda = [](Elem1*, Elem2*) { return false; }; - STATIC_ASSERT(_Equal_memcmp_is_safe == false); + STATIC_ASSERT(_Can_memcmp_in_equal == false); // equal_to should not explode - STATIC_ASSERT(_Equal_memcmp_is_safe> == (Expected && is_same_v) ); + STATIC_ASSERT(_Can_memcmp_in_equal> == (Expected && is_same_v) ); // But again, not volatile - STATIC_ASSERT(_Equal_memcmp_is_safe> == false); - STATIC_ASSERT(_Equal_memcmp_is_safe> == false); + STATIC_ASSERT(_Can_memcmp_in_equal> == false); + STATIC_ASSERT(_Can_memcmp_in_equal> == false); } void equal_safe_test_cases() { From 8a9f343bd944369977dba1a654b256b54cc231d9 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Wed, 7 Oct 2020 14:27:11 +0200 Subject: [PATCH 4/8] Use _Memop_in_algorithm_is_safe --- stl/inc/algorithm | 14 +- stl/inc/memory | 30 ++-- stl/inc/vector | 4 +- stl/inc/xmemory | 27 ++-- stl/inc/xutility | 54 +++---- tests/std/tests/VSO_0180469_ptr_cat/test.cpp | 142 ++++++++++--------- 6 files changed, 139 insertions(+), 132 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 895f5813b4..779ab60956 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1850,7 +1850,7 @@ namespace ranges { template requires indirectly_movable<_It1, _It2> _NODISCARD constexpr _It2 _Move_backward_common(const _It1 _First, _It1 _Last, _It2 _Result) { - if constexpr (_Can_memmove_in_move<_It1, _It2>) { + if constexpr (_Memmove_in_move_is_safe<_It1, _It2>) { if (!_STD is_constant_evaluated()) { return _Copy_backward_memmove(_First, _Last, _Result); } @@ -2217,7 +2217,7 @@ namespace ranges { template _NODISCARD _CONSTEXPR20 bool _Equal_rev_pred_unchecked(_InIt1 _First1, _InIt2 _First2, const _InIt2 _Last2, _Pr _Pred) { // compare [_First1, ...) to [_First2, _Last2) - if constexpr (_Can_memcmp_in_equal<_InIt1, _InIt2, _Pr>) { + if constexpr (_Memcmp_in_equal_is_safe<_InIt1, _InIt2, _Pr>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -2238,7 +2238,7 @@ _NODISCARD _CONSTEXPR20 bool _Equal_rev_pred_unchecked(_InIt1 _First1, _InIt2 _F return true; } #else // ^^^ _HAS_IF_CONSTEXPR ^^^ // vvv !_HAS_IF_CONSTEXPR vvv -template , int> = 0> +template , int> = 0> bool _Equal_rev_pred_unchecked(_InIt1 _First1, _InIt2 _First2, const _InIt2 _Last2, _Pr _Pred) { // compare [_First1, ...) to [_First2, _Last2), no special optimization for (; _First2 != _Last2; ++_First1, (void) ++_First2) { @@ -2250,7 +2250,7 @@ bool _Equal_rev_pred_unchecked(_InIt1 _First1, _InIt2 _First2, const _InIt2 _Las return true; } -template , int> = 0> +template , int> = 0> bool _Equal_rev_pred_unchecked(const _InIt1 _First1, const _InIt2 _First2, const _InIt2 _Last2, _Pr) { // compare [_First1, ...) to [_First2, _Last2), memcmp optimization const auto _First1_ch = reinterpret_cast(_First1); @@ -2391,7 +2391,7 @@ namespace ranges { // clang-format off template concept _Equal_rev_pred_can_memcmp = is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity> - && is_same_v<_Se2, _It2> && _Can_memcmp_in_equal<_It1, _It2, _Pr>; + && is_same_v<_Se2, _It2> && _Memcmp_in_equal_is_safe<_It1, _It2, _Pr>; template _Se2, class _Pr, class _Pj1, class _Pj2> requires indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2> @@ -3938,7 +3938,7 @@ namespace ranges { _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_STD move(_First)); const auto _ULast = _Get_unwrapped(_STD move(_Last)); - if constexpr (_Can_memset_in_fill) { + if constexpr (_Memset_in_fill_is_safe) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -3978,7 +3978,7 @@ namespace ranges { constexpr _It operator()(_It _First, iter_difference_t<_It> _Count, const _Ty& _Value) const { if (_Count > 0) { auto _UFirst = _Get_unwrapped_n(_STD move(_First), _Count); - if constexpr (_Can_memset_in_fill) { + if constexpr (_Memset_in_fill_is_safe) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated diff --git a/stl/inc/memory b/stl/inc/memory index f77b03f06b..7670f03485 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -107,7 +107,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(_No_throw_sentinel_for<_OSe, _Out>); _STL_INTERNAL_STATIC_ASSERT(constructible_from, iter_reference_t<_It>>); - if constexpr (is_same_v<_Se, _It> && _Can_memmove_in_uninitialized_copy<_It, _Out>) { + if constexpr (is_same_v<_Se, _It> && _Memmove_in_uninitialized_copy_is_safe<_It, _Out>) { return _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -137,7 +137,7 @@ _NoThrowFwdIt uninitialized_copy_n(const _InIt _First, const _Diff _Count_raw, _ auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Can_memmove_in_uninitialized_copy) { + if constexpr (_Memmove_in_uninitialized_copy_is_safe) { _UDest = _Copy_memmove(_UFirst, _UFirst + _Count, _UDest); } else { _Uninitialized_backout _Backout{_UDest}; @@ -181,8 +181,9 @@ _NoThrowFwdIt uninitialized_copy_n(const _InIt _First, const _Diff _Count_raw, _ auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); - _Seek_wrapped(_Dest, _Uninitialized_copy_n_unchecked2(_UFirst, _Count, _UDest, - bool_constant<_Can_memmove_in_uninitialized_copy>{})); + _Seek_wrapped( + _Dest, _Uninitialized_copy_n_unchecked2(_UFirst, _Count, _UDest, + bool_constant<_Memmove_in_uninitialized_copy_is_safe>{})); return _Dest; } #endif // _HAS_IF_CONSTEXPR @@ -212,7 +213,7 @@ namespace ranges { auto _IFirst = _Get_unwrapped_n(_STD move(_First1), _Count); auto _OFirst = _Get_unwrapped(_STD move(_First2)); const auto _OLast = _Get_unwrapped(_STD move(_Last2)); - if constexpr (_Can_memmove_in_uninitialized_copy<_It, _Out>) { + if constexpr (_Memmove_in_uninitialized_copy_is_safe<_It, _Out>) { _OFirst = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -299,7 +300,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(_No_throw_sentinel_for<_OSe, _Out>); _STL_INTERNAL_STATIC_ASSERT(constructible_from, iter_rvalue_reference_t<_It>>); - if constexpr (is_same_v<_Se, _It> && _Can_memmove_in_uninitialized_move<_It, _Out>) { + if constexpr (is_same_v<_Se, _It> && _Memmove_in_uninitialized_move_is_safe<_It, _Out>) { return _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -328,7 +329,7 @@ pair<_InIt, _NoThrowFwdIt> uninitialized_move_n(_InIt _First, const _Diff _Count auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Can_memmove_in_uninitialized_move) { + if constexpr (_Memmove_in_uninitialized_move_is_safe) { _UDest = _Copy_memmove(_UFirst, _UFirst + _Count, _UDest); _UFirst += _Count; } else { @@ -373,7 +374,7 @@ namespace ranges { auto _IFirst = _Get_unwrapped_n(_STD move(_First1), _Count); auto _OFirst = _Get_unwrapped(_STD move(_First2)); const auto _OLast = _Get_unwrapped(_STD move(_Last2)); - if constexpr (_Can_memmove_in_uninitialized_move<_It, _Out>) { + if constexpr (_Memmove_in_uninitialized_move_is_safe<_It, _Out>) { _OFirst = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -426,7 +427,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(_No_throw_sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(constructible_from, const _Ty&>); - if constexpr (_Can_memset_in_fill<_It, _Ty>) { + if constexpr (_Memset_in_fill_is_safe<_It, _Ty>) { const auto _OFinal = _RANGES next(_OFirst, _STD move(_OLast)); const auto _Diff = static_cast(_OFinal - _OFirst); _Fill_memset(_OFirst, _Val, _Diff); @@ -458,7 +459,7 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, } auto _UFirst = _Get_unwrapped_n(_First, _Count); - if constexpr (_Can_memset_in_fill<_Unwrapped_n_t, _Tval>) { + if constexpr (_Memset_in_fill_is_safe<_Unwrapped_n_t, _Tval>) { _Fill_memset(_UFirst, _Val, static_cast(_Count)); _UFirst += _Count; } else { @@ -505,7 +506,7 @@ _NoThrowFwdIt uninitialized_fill_n(_NoThrowFwdIt _First, const _Diff _Count_raw, auto _UFirst = _Get_unwrapped_n(_STD move(_First), _Count); _Seek_wrapped(_First, _Uninitialized_fill_n_unchecked1(_STD move(_UFirst), _Count, _Val, - bool_constant<_Can_memset_in_fill<_Unwrapped_t<_NoThrowFwdIt>, _Tval>>{})); + bool_constant<_Memset_in_fill_is_safe<_Unwrapped_t<_NoThrowFwdIt>, _Tval>>{})); return _First; } #endif // _HAS_IF_CONSTEXPR @@ -527,7 +528,7 @@ namespace ranges { } auto _UFirst = _Get_unwrapped_n(_STD move(_First), _Count); - if constexpr (_Can_memset_in_fill<_It, _Ty>) { + if constexpr (_Memset_in_fill_is_safe<_It, _Ty>) { _Fill_memset(_UFirst, _Val, static_cast(_Count)); _Seek_wrapped(_First, _UFirst + _Count); } else { @@ -2359,7 +2360,7 @@ void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, _Uninitialized_copy_multidimensional(_Val, _Out[_Idx]); // intentionally copy, not fill } _Guard._Target = nullptr; - } else if constexpr (_Can_memset_in_fill<_Ty*, _Ty>) { + } else if constexpr (_Memset_in_fill_is_safe<_Ty*, _Ty>) { _Fill_memset(_Out, _Val, _Size); } else { _Uninitialized_rev_destroying_backout _Backout{_Out}; @@ -2682,7 +2683,8 @@ void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Si _Uninitialized_copy_multidimensional_al(_Val, _Out[_Idx], _Al); // intentionally copy, not fill } _Guard._Target = nullptr; - } else if constexpr (_Can_memset_in_fill<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, const _Ty&>::value) { + } else if constexpr (_Memset_in_fill_is_safe<_Ty*, + _Ty> && _Uses_default_construct<_Alloc, _Ty*, const _Ty&>::value) { _Fill_memset(_Out, _Val, _Size); } else { _Uninitialized_rev_destroying_backout_al _Backout{_Out, _Al}; diff --git a/stl/inc/vector b/stl/inc/vector index 6a72a54a1c..5a20178c26 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -636,7 +636,7 @@ private: const auto _Oldcapacity = static_cast(_My_data._Myend - _Myfirst); #if _HAS_IF_CONSTEXPR - if constexpr (conjunction_v>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alty, _Ty*, _Ty>, _Uses_default_destroy<_Alty, _Ty*>>) { if (_Newsize > _Oldcapacity) { _Clear_and_reserve_geometric(_Newsize); @@ -1108,7 +1108,7 @@ private: _My_data._Orphan_all(); #if _HAS_IF_CONSTEXPR - if constexpr (conjunction_v>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alty, _Ty*, decltype(*_First)>, _Uses_default_destroy<_Alty, _Ty*>>) { const auto _Oldcapacity = static_cast(_Myend - _Myfirst); diff --git a/stl/inc/xmemory b/stl/inc/xmemory index eb6962bba0..d10cb91aab 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1480,7 +1480,7 @@ namespace ranges { template _NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // move [_First, _Last) to raw [_Dest, ...) - if constexpr (_Can_memmove_in_uninitialized_move<_InIt, _NoThrowFwdIt>) { + if constexpr (_Memmove_in_uninitialized_move_is_safe<_InIt, _NoThrowFwdIt>) { return _Copy_memmove(_First, _Last, _Dest); } else { _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; @@ -1514,7 +1514,7 @@ template _NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // move [_First, _Last) to raw [_Dest, ...), choose optimization return _Uninitialized_move_unchecked1( - _First, _Last, _Dest, bool_constant<_Can_memmove_in_uninitialized_move<_InIt, _NoThrowFwdIt>>{}); + _First, _Last, _Dest, bool_constant<_Memmove_in_uninitialized_move_is_safe<_InIt, _NoThrowFwdIt>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -1562,7 +1562,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy( auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (conjunction_v>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>) { _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); _Dest += _ULast - _UFirst; @@ -1610,7 +1610,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy( using _Ptrval = typename _Alloc::value_type*; return _Uninitialized_copy_al_unchecked(_UFirst, _ULast, _Dest, _Al, - bool_constant>, + bool_constant>, _Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -1624,7 +1624,7 @@ _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrow auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast)); - if constexpr (_Can_memmove_in_uninitialized_copy) { + if constexpr (_Memmove_in_uninitialized_copy_is_safe) { _UDest = _Copy_memmove(_UFirst, _ULast, _UDest); } else { _Uninitialized_backout _Backout{_UDest}; @@ -1664,8 +1664,9 @@ _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrow auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast)); - _Seek_wrapped(_Dest, _Uninitialized_copy_unchecked(_UFirst, _ULast, _UDest, - bool_constant<_Can_memmove_in_uninitialized_copy>{})); + _Seek_wrapped( + _Dest, _Uninitialized_copy_unchecked(_UFirst, _ULast, _UDest, + bool_constant<_Memmove_in_uninitialized_copy_is_safe>{})); return _Dest; } #endif // _HAS_IF_CONSTEXPR @@ -1680,7 +1681,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_move( using _Ptrval = typename _Alloc::value_type*; auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (conjunction_v>, + if constexpr (conjunction_v>, _Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>>) { _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); return _Dest + (_ULast - _UFirst); @@ -1729,7 +1730,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_move( using _Ptrval = typename _Alloc::value_type*; _Seek_wrapped(_Dest, _Uninitialized_move_al_unchecked(_UFirst, _ULast, _UDest, _Al, - bool_constant < _Can_memmove_in_uninitialized_move && _Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>::value > {})); return _Dest; } @@ -1742,7 +1743,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n( _Alloc_ptr_t<_Alloc> _First, _Alloc_size_t<_Alloc> _Count, const typename _Alloc::value_type& _Val, _Alloc& _Al) { // copy _Count copies of _Val to raw _First, using _Al using _Ty = typename _Alloc::value_type; - if constexpr (_Can_memset_in_fill<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { + if constexpr (_Memset_in_fill_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { _Fill_memset(_Unfancy(_First), _Val, static_cast(_Count)); return _First + _Count; } else { @@ -1781,7 +1782,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n(_Alloc_ptr_t<_Alloc> _First, const _A // copy _Count copies of _Val to raw _First, using _Al using _Ty = typename _Alloc::value_type; return _Uninit_alloc_fill_n1(_First, _Count, _Val, _Al, - bool_constant < _Can_memset_in_fill<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value > {}); + bool_constant < _Memset_in_fill_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value > {}); } #endif // _HAS_IF_CONSTEXPR @@ -1793,7 +1794,7 @@ void uninitialized_fill(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, c _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (_Can_memset_in_fill<_Unwrapped_t, _Tval>) { + if constexpr (_Memset_in_fill_is_safe<_Unwrapped_t, _Tval>) { _Fill_memset(_UFirst, _Val, static_cast(_ULast - _UFirst)); } else { _Uninitialized_backout<_Unwrapped_t> _Backout{_UFirst}; @@ -1830,7 +1831,7 @@ void uninitialized_fill(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, c _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); _Uninitialized_fill_unchecked(_UFirst, _Get_unwrapped(_Last), _Val, - bool_constant<_Can_memset_in_fill<_Unwrapped_t, _Tval>>{}); + bool_constant<_Memset_in_fill_is_safe<_Unwrapped_t, _Tval>>{}); } #endif // _HAS_IF_CONSTEXPR diff --git a/stl/inc/xutility b/stl/inc/xutility index b0b8b76313..4d5903e200 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4392,17 +4392,19 @@ _INLINE_VAR constexpr bool _Can_memop, _IterDest, _Ca _Can_memop<_IterSource, _IterDest, _Cat>; template -_INLINE_VAR constexpr bool _Can_memmove_in_copy = _Can_memop, _IterDest, _Memop_cat::_Copy>; +_INLINE_VAR constexpr bool _Memmove_in_copy_is_safe = + _Can_memop, _IterDest, _Memop_cat::_Copy>; template -_INLINE_VAR constexpr bool _Can_memmove_in_uninitialized_copy = +_INLINE_VAR constexpr bool _Memmove_in_uninitialized_copy_is_safe = _Can_memop, _IterDest, _Memop_cat::_Copy_uninitialized>; template -_INLINE_VAR constexpr bool _Can_memmove_in_move = _Can_memop, _IterDest, _Memop_cat::_Move>; +_INLINE_VAR constexpr bool _Memmove_in_move_is_safe = + _Can_memop, _IterDest, _Memop_cat::_Move>; template -_INLINE_VAR constexpr bool _Can_memmove_in_uninitialized_move = +_INLINE_VAR constexpr bool _Memmove_in_uninitialized_move_is_safe = _Can_memop, _IterDest, _Memop_cat::_Move_uninitialized>; template @@ -4440,7 +4442,7 @@ template _CONSTEXPR20 _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) // note: _Copy_unchecked has callers other than the copy family - if constexpr (_Can_memmove_in_copy<_InIt, _OutIt>) { + if constexpr (_Memmove_in_copy_is_safe<_InIt, _OutIt>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4476,7 +4478,7 @@ template _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // copy [_First, _Last) to [_Dest, ...) // note: _Copy_unchecked has callers other than the copy family - return _Copy_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memmove_in_copy<_InIt, _OutIt>>{}); + return _Copy_unchecked1(_First, _Last, _Dest, bool_constant<_Memmove_in_copy_is_safe<_InIt, _OutIt>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -4510,7 +4512,7 @@ _CONSTEXPR20 _OutIt copy_n(_InIt _First, _Diff _Count_raw, _OutIt _Dest) { if (0 < _Count) { auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Can_memmove_in_copy) { + if constexpr (_Memmove_in_copy_is_safe) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4571,7 +4573,7 @@ _OutIt copy_n(_InIt _First, _Diff _Count_raw, _OutIt _Dest) { // copy [_First, _ auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); _Seek_wrapped(_Dest, _Copy_n_unchecked4(_UFirst, _Count, _UDest, - bool_constant<_Can_memmove_in_copy>{})); + bool_constant<_Memmove_in_copy_is_safe>{})); } return _Dest; @@ -4609,7 +4611,7 @@ _BidIt2 _Copy_backward_memmove(move_iterator<_BidIt1> _First, move_iterator<_Bid template _NODISCARD _CONSTEXPR20 _BidIt2 _Copy_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // copy [_First, _Last) backwards to [..., _Dest) - if constexpr (_Can_memmove_in_copy<_BidIt1, _BidIt2>) { + if constexpr (_Memmove_in_copy_is_safe<_BidIt1, _BidIt2>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4659,7 +4661,7 @@ _BidIt2 copy_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // copy [_ const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, -_Idl_distance<_BidIt1>(_UFirst, _ULast)); _Seek_wrapped(_Dest, _Copy_backward_unchecked(_UFirst, _ULast, _UDest, - bool_constant<_Can_memmove_in_copy>{})); + bool_constant<_Memmove_in_copy_is_safe>{})); return _Dest; } #endif // _HAS_IF_CONSTEXPR @@ -4679,7 +4681,7 @@ template _CONSTEXPR20 _OutIt _Move_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // move [_First, _Last) to [_Dest, ...) // note: _Move_unchecked has callers other than the move family - if constexpr (_Can_memmove_in_move<_InIt, _OutIt>) { + if constexpr (_Memmove_in_move_is_safe<_InIt, _OutIt>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4715,7 +4717,7 @@ template _OutIt _Move_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { // move [_First, _Last) to [_Dest, ...), choose optimization // note: _Move_unchecked has callers other than the move family - return _Move_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memmove_in_move<_InIt, _OutIt>>{}); + return _Move_unchecked1(_First, _Last, _Dest, bool_constant<_Memmove_in_move_is_safe<_InIt, _OutIt>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -4747,7 +4749,7 @@ template _CONSTEXPR20 _BidIt2 _Move_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // move [_First, _Last) backwards to [..., _Dest) // note: _Move_backward_unchecked has callers other than the move_backward family - if constexpr (_Can_memmove_in_move<_BidIt1, _BidIt2>) { + if constexpr (_Memmove_in_move_is_safe<_BidIt1, _BidIt2>) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4783,7 +4785,7 @@ template _BidIt2 _Move_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // move [_First, _Last) backwards to [..., _Dest), choose optimization // note: _Move_backward_unchecked has callers other than the move_backward family - return _Move_backward_unchecked1(_First, _Last, _Dest, bool_constant<_Can_memmove_in_move<_BidIt1, _BidIt2>>{}); + return _Move_backward_unchecked1(_First, _Last, _Dest, bool_constant<_Memmove_in_move_is_safe<_BidIt1, _BidIt2>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -4836,14 +4838,14 @@ struct _Is_character_or_byte_or_bool : true_type {}; template <> struct _Is_character_or_byte_or_bool : true_type {}; -// _Can_memset_in_fill determines if _FwdIt and _Ty are eligible for memset optimization in fill +// _Memset_in_fill_is_safe determines if _FwdIt and _Ty are eligible for memset optimization in fill template > -_INLINE_VAR constexpr bool _Can_memset_in_fill = conjunction_v, +_INLINE_VAR constexpr bool _Memset_in_fill_is_safe = conjunction_v, _Is_character_or_byte_or_bool<_Unwrap_enum_t>>>, is_assignable<_Iter_ref_t<_FwdIt>, const _Ty&>>; template -_INLINE_VAR constexpr bool _Can_memset_in_fill<_FwdIt, _Ty, false> = false; +_INLINE_VAR constexpr bool _Memset_in_fill_is_safe<_FwdIt, _Ty, false> = false; template void _Fill_memset(_DestTy* const _Dest, const _Ty _Val, const size_t _Count) { @@ -4861,7 +4863,7 @@ _CONSTEXPR20 void fill(const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) } else { auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); - if constexpr (_Can_memset_in_fill) { + if constexpr (_Memset_in_fill_is_safe) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4895,7 +4897,7 @@ template void fill(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { // copy _Val through [_First, _Last) _Adl_verify_range(_First, _Last); _Fill_unchecked1(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Val, - bool_constant<_Can_memset_in_fill<_Unwrapped_t, _Ty>>{}); + bool_constant<_Memset_in_fill_is_safe<_Unwrapped_t, _Ty>>{}); } #endif // _HAS_IF_CONSTEXPR @@ -4922,7 +4924,7 @@ _CONSTEXPR20 _OutIt fill_n(_OutIt _Dest, const _Diff _Count_raw, const _Ty& _Val return _Last; } else { auto _UDest = _Get_unwrapped_n(_Dest, _Count); - if constexpr (_Can_memset_in_fill) { + if constexpr (_Memset_in_fill_is_safe) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -4969,7 +4971,7 @@ _OutIt fill_n(_OutIt _Dest, const _Diff _Count_raw, const _Ty& _Val) { if (0 < _Count) { auto _UDest = _Get_unwrapped_n(_Dest, _Count); _Seek_wrapped(_Dest, - _Fill_n_unchecked2(_UDest, _Count, _Val, bool_constant<_Can_memset_in_fill>{})); + _Fill_n_unchecked2(_UDest, _Count, _Val, bool_constant<_Memset_in_fill_is_safe>{})); } return _Dest; @@ -5052,7 +5054,7 @@ template _INLINE_VAR constexpr bool _Can_memcmp_elements_with_pred = _Can_memcmp_elements<_Elem1, _Elem2> // && _Pred_is_consistent_with_memcmp<_Elem1, _Elem2, _Pr>; -// _Can_memcmp_in_equal<_Iter1, _Iter2, _Pr> reports whether we can activate the memcmp optimization +// _Memcmp_in_equal_is_safe<_Iter1, _Iter2, _Pr> reports whether we can activate the memcmp optimization // for arbitrary iterators and predicates. // It ignores top-level constness on the iterators and on the elements. template @@ -5061,7 +5063,7 @@ _INLINE_VAR constexpr bool _Equal_memcmp_is_safe_helper = _Iterators_are_contigu remove_const_t>>, _Pr>; template -_INLINE_VAR constexpr bool _Can_memcmp_in_equal = +_INLINE_VAR constexpr bool _Memcmp_in_equal_is_safe = _Equal_memcmp_is_safe_helper, remove_const_t<_Iter2>, _Pr>; #if _HAS_IF_CONSTEXPR @@ -5072,7 +5074,7 @@ _NODISCARD _CONSTEXPR20 bool equal(const _InIt1 _First1, const _InIt1 _Last1, co auto _UFirst1 = _Get_unwrapped(_First1); const auto _ULast1 = _Get_unwrapped(_Last1); auto _UFirst2 = _Get_unwrapped_n(_First2, _Idl_distance<_InIt1>(_UFirst1, _ULast1)); - if constexpr (_Can_memcmp_in_equal) { + if constexpr (_Memcmp_in_equal_is_safe) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated @@ -5093,7 +5095,7 @@ _NODISCARD _CONSTEXPR20 bool equal(const _InIt1 _First1, const _InIt1 _Last1, co return true; } #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv -template , int> = 0> +template , int> = 0> bool _Equal_unchecked(_InIt1 _First1, const _InIt1 _Last1, _InIt2 _First2, _Pr _Pred) { // compare [_First1, _Last1) to [_First2, ...), no special optimization for (; _First1 != _Last1; ++_First1, (void) ++_First2) { @@ -5105,7 +5107,7 @@ bool _Equal_unchecked(_InIt1 _First1, const _InIt1 _Last1, _InIt2 _First2, _Pr _ return true; } -template , int> = 0> +template , int> = 0> bool _Equal_unchecked(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _Pr) { // compare [_First1, _Last1) to [_First2, ...), memcmp optimization const auto _First1_ch = reinterpret_cast(_First1); diff --git a/tests/std/tests/VSO_0180469_ptr_cat/test.cpp b/tests/std/tests/VSO_0180469_ptr_cat/test.cpp index ed6ad8137c..e30b3656a9 100644 --- a/tests/std/tests/VSO_0180469_ptr_cat/test.cpp +++ b/tests/std/tests/VSO_0180469_ptr_cat/test.cpp @@ -31,13 +31,13 @@ void assert_same() { template struct test_ptr_cat_helper { - static constexpr bool CopyReallyTrivial = _Can_memmove_in_uninitialized_copy; - static constexpr bool CopyTriviallyCopyable = _Can_memmove_in_copy; + static constexpr bool CopyReallyTrivial = _Memmove_in_uninitialized_copy_is_safe; + static constexpr bool CopyTriviallyCopyable = _Memmove_in_copy_is_safe; STATIC_ASSERT(Expected == CopyReallyTrivial + CopyTriviallyCopyable); STATIC_ASSERT(!CopyReallyTrivial || CopyTriviallyCopyable); - static constexpr bool MoveReallyTrivial = _Can_memmove_in_uninitialized_move; - static constexpr bool MoveTriviallyCopyable = _Can_memmove_in_move; + static constexpr bool MoveReallyTrivial = _Memmove_in_uninitialized_move_is_safe; + static constexpr bool MoveTriviallyCopyable = _Memmove_in_move_is_safe; STATIC_ASSERT(Expected == MoveReallyTrivial + MoveTriviallyCopyable); STATIC_ASSERT(!MoveReallyTrivial || MoveTriviallyCopyable); }; @@ -234,104 +234,106 @@ void ptr_cat_test_cases() { template void test_case_Equal_memcmp_is_safe_comparator() { // Default case - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); // Adding const should not change the answer - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); // Top level const should not change the answer - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == Expected); // Adding volatile anywhere should explode - STATIC_ASSERT(_Can_memcmp_in_equal == false); - STATIC_ASSERT(_Can_memcmp_in_equal == false); - STATIC_ASSERT(_Can_memcmp_in_equal == false); - STATIC_ASSERT(_Can_memcmp_in_equal == false); - STATIC_ASSERT(_Can_memcmp_in_equal == false); - STATIC_ASSERT(_Can_memcmp_in_equal == false); - STATIC_ASSERT(_Can_memcmp_in_equal == false); - STATIC_ASSERT(_Can_memcmp_in_equal == false); - STATIC_ASSERT(_Can_memcmp_in_equal == false); - STATIC_ASSERT(_Can_memcmp_in_equal == false); - STATIC_ASSERT(_Can_memcmp_in_equal == false); - STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); #ifdef __cpp_lib_concepts // contiguous iterators should not change the answer if constexpr (!is_same_v && !is_same_v) { // vector::iterator is not contiguous - STATIC_ASSERT( - _Can_memcmp_in_equal::iterator, typename vector::iterator, Pr> == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal::const_iterator, + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, typename vector::iterator, + Pr> == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe::const_iterator, typename vector::const_iterator, Pr> == Expected); } - STATIC_ASSERT( - _Can_memcmp_in_equal::iterator, typename array::iterator, Pr> == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal::const_iterator, + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, typename array::iterator, + Pr> == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe::const_iterator, typename array::const_iterator, Pr> == Expected); // Mixing contiguous iterators should not change the answer if constexpr (!is_same_v && !is_same_v) { - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename vector::const_iterator, + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, typename vector::const_iterator, Pr> == Expected); } if constexpr (!is_same_v) { - STATIC_ASSERT(_Can_memcmp_in_equal::const_iterator, + STATIC_ASSERT(_Memcmp_in_equal_is_safe::const_iterator, typename vector::const_iterator, Pr> == Expected); } if constexpr (!is_same_v) { - STATIC_ASSERT( - _Can_memcmp_in_equal::iterator, typename array::iterator, Pr> == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename array::const_iterator, + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, typename array::iterator, Pr> == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, + typename array::const_iterator, Pr> == Expected); } // span iterators are contiguous - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == Expected); STATIC_ASSERT( - _Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == Expected); + _Memcmp_in_equal_is_safe::iterator, typename span::iterator, Pr> == Expected); STATIC_ASSERT( - _Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == Expected); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, + _Memcmp_in_equal_is_safe::iterator, typename span::iterator, Pr> == Expected); + STATIC_ASSERT( + _Memcmp_in_equal_is_safe::iterator, typename span::iterator, Pr> == Expected); + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, typename span::iterator, Pr> == Expected); // contiguous iterators to volatile should explode STATIC_ASSERT( - _Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); + _Memcmp_in_equal_is_safe::iterator, typename span::iterator, Pr> == false); STATIC_ASSERT( - _Can_memcmp_in_equal::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, - Pr> == false); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, - Pr> == false); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, - Pr> == false); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, + _Memcmp_in_equal_is_safe::iterator, typename span::iterator, Pr> == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, + typename span::iterator, Pr> == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, + typename span::iterator, Pr> == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, - Pr> == false); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename span::iterator, - Pr> == false); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, + typename span::iterator, Pr> == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, + typename span::iterator, Pr> == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, + typename span::iterator, Pr> == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, typename span::iterator, Pr> == false); - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, + STATIC_ASSERT(_Memcmp_in_equal_is_safe::iterator, typename span::iterator, Pr> == false); #endif // __cpp_lib_concepts // Non-contiguous iterators should explode - STATIC_ASSERT(_Can_memcmp_in_equal::iterator, typename list::iterator, Pr> == false); + STATIC_ASSERT( + _Memcmp_in_equal_is_safe::iterator, typename list::iterator, Pr> == false); } template @@ -343,15 +345,15 @@ void test_case_Equal_memcmp_is_safe() { #endif // __cpp_lib_concepts // equal_to< some other T > should explode - STATIC_ASSERT(_Can_memcmp_in_equal>> == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe>> == false); // Non equal_to comparison functions should explode auto lambda = [](Elem1*, Elem2*) { return false; }; - STATIC_ASSERT(_Can_memcmp_in_equal == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe == false); // equal_to should not explode - STATIC_ASSERT(_Can_memcmp_in_equal> == (Expected && is_same_v) ); + STATIC_ASSERT(_Memcmp_in_equal_is_safe> == (Expected && is_same_v) ); // But again, not volatile - STATIC_ASSERT(_Can_memcmp_in_equal> == false); - STATIC_ASSERT(_Can_memcmp_in_equal> == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe> == false); + STATIC_ASSERT(_Memcmp_in_equal_is_safe> == false); } void equal_safe_test_cases() { From ae2dfb178dd0a5062ed7cafe134f217dd1fc551b Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Mon, 12 Oct 2020 20:56:18 +0200 Subject: [PATCH 5/8] Use _Memmove_meow as we use it ouside of copy algorithms --- stl/inc/algorithm | 2 +- stl/inc/memory | 18 +++++++++--------- stl/inc/vector | 4 ++-- stl/inc/xmemory | 16 ++++++++-------- stl/inc/xutility | 36 ++++++++++++++++++------------------ 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 779ab60956..a027ca8371 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1852,7 +1852,7 @@ namespace ranges { _NODISCARD constexpr _It2 _Move_backward_common(const _It1 _First, _It1 _Last, _It2 _Result) { if constexpr (_Memmove_in_move_is_safe<_It1, _It2>) { if (!_STD is_constant_evaluated()) { - return _Copy_backward_memmove(_First, _Last, _Result); + return _Memmove_backward(_First, _Last, _Result); } } diff --git a/stl/inc/memory b/stl/inc/memory index 7670f03485..bc16c897de 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -108,7 +108,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(constructible_from, iter_reference_t<_It>>); if constexpr (is_same_v<_Se, _It> && _Memmove_in_uninitialized_copy_is_safe<_It, _Out>) { - return _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast); + return _Memmove_forward_common(_IFirst, _ILast, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -138,7 +138,7 @@ _NoThrowFwdIt uninitialized_copy_n(const _InIt _First, const _Diff _Count_raw, _ auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); if constexpr (_Memmove_in_uninitialized_copy_is_safe) { - _UDest = _Copy_memmove(_UFirst, _UFirst + _Count, _UDest); + _UDest = _Memmove_forward(_UFirst, _UFirst + _Count, _UDest); } else { _Uninitialized_backout _Backout{_UDest}; @@ -168,7 +168,7 @@ _NoThrowFwdIt _Uninitialized_copy_n_unchecked2(_InIt _First, _Diff _Count, const template _NoThrowFwdIt _Uninitialized_copy_n_unchecked2(const _InIt _First, const _Diff _Count, const _NoThrowFwdIt _Dest, true_type) { // copy [_First, _First + _Count) to [_Dest, ...), memmove optimization - return _Copy_memmove(_First, _First + _Count, _Dest); + return _Memmove_forward(_First, _First + _Count, _Dest); } template @@ -214,7 +214,7 @@ namespace ranges { auto _OFirst = _Get_unwrapped(_STD move(_First2)); const auto _OLast = _Get_unwrapped(_STD move(_Last2)); if constexpr (_Memmove_in_uninitialized_copy_is_safe<_It, _Out>) { - _OFirst = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); + _OFirst = _Memmove_forward_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -301,7 +301,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(constructible_from, iter_rvalue_reference_t<_It>>); if constexpr (is_same_v<_Se, _It> && _Memmove_in_uninitialized_move_is_safe<_It, _Out>) { - return _Copy_memcpy_common(_IFirst, _ILast, _OFirst, _OLast); + return _Memmove_forward_common(_IFirst, _ILast, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -330,7 +330,7 @@ pair<_InIt, _NoThrowFwdIt> uninitialized_move_n(_InIt _First, const _Diff _Count auto _UFirst = _Get_unwrapped_n(_First, _Count); auto _UDest = _Get_unwrapped_n(_Dest, _Count); if constexpr (_Memmove_in_uninitialized_move_is_safe) { - _UDest = _Copy_memmove(_UFirst, _UFirst + _Count, _UDest); + _UDest = _Memmove_forward(_UFirst, _UFirst + _Count, _UDest); _UFirst += _Count; } else { _Uninitialized_backout _Backout{_UDest}; @@ -375,7 +375,7 @@ namespace ranges { auto _OFirst = _Get_unwrapped(_STD move(_First2)); const auto _OLast = _Get_unwrapped(_STD move(_Last2)); if constexpr (_Memmove_in_uninitialized_move_is_safe<_It, _Out>) { - _OFirst = _Copy_memcpy_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); + _OFirst = _Memmove_forward_common(_IFirst, _IFirst + _Count, _OFirst, _OLast); } else { _Uninitialized_backout _Backout{_STD move(_OFirst)}; @@ -2316,7 +2316,7 @@ struct _Reverse_destroy_multidimensional_n_guard { template void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size]) { if constexpr (is_trivial_v<_Ty>) { - _Copy_memmove(_In, _In + _Size, _Out); + _Memmove_forward(_In, _In + _Size, _Out); } else if constexpr (is_array_v<_Ty>) { _Reverse_destroy_multidimensional_n_guard<_Ty> _Guard{_Out, 0}; for (size_t& _Idx = _Guard._Index; _Idx < _Size; ++_Idx) { @@ -2639,7 +2639,7 @@ template void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size], _Alloc& _Al) { using _Item = remove_all_extents_t<_Ty>; if constexpr (conjunction_v, _Uses_default_construct<_Alloc, _Item*, const _Item&>>) { - _Copy_memmove(_In, _In + _Size, _Out); + _Memmove_forward(_In, _In + _Size, _Out); } else if constexpr (is_array_v<_Ty>) { _Reverse_destroy_multidimensional_n_al_guard<_Ty, _Alloc> _Guard{_Out, 0, _Al}; for (size_t& _Idx = _Guard._Index; _Idx < _Size; ++_Idx) { diff --git a/stl/inc/vector b/stl/inc/vector index 5a20178c26..348c80a216 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -642,7 +642,7 @@ private: _Clear_and_reserve_geometric(_Newsize); } - _Mylast = _Refancy(_Copy_memmove(_Unfancy(_First), _Unfancy(_Last), _Unfancy(_Myfirst))); + _Mylast = _Refancy(_Memmove_forward(_Unfancy(_First), _Unfancy(_Last), _Unfancy(_Myfirst))); } else #endif // _HAS_IF_CONSTEXPR { @@ -1116,7 +1116,7 @@ private: _Clear_and_reserve_geometric(_Newsize); } - _Mylast = _Refancy(_Copy_memmove(_First, _Last, _Unfancy(_Myfirst))); + _Mylast = _Refancy(_Memmove_forward(_First, _Last, _Unfancy(_Myfirst))); } else #endif // _HAS_IF_CONSTEXPR { diff --git a/stl/inc/xmemory b/stl/inc/xmemory index d10cb91aab..19bcb23411 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1481,7 +1481,7 @@ template _NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // move [_First, _Last) to raw [_Dest, ...) if constexpr (_Memmove_in_uninitialized_move_is_safe<_InIt, _NoThrowFwdIt>) { - return _Copy_memmove(_First, _Last, _Dest); + return _Memmove_forward(_First, _Last, _Dest); } else { _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; for (; _First != _Last; ++_First) { @@ -1507,7 +1507,7 @@ template _NoThrowFwdIt _Uninitialized_move_unchecked1( const _InIt _First, const _InIt _Last, const _NoThrowFwdIt _Dest, true_type) { // move [_First, _Last) to raw [_Dest, ...), memmove optimization - return _Copy_memmove(_First, _Last, _Dest); + return _Memmove_forward(_First, _Last, _Dest); } template @@ -1564,7 +1564,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy( if constexpr (conjunction_v>, _Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>) { - _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); + _Memmove_forward(_UFirst, _ULast, _Unfancy(_Dest)); _Dest += _ULast - _UFirst; } else { _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al}; @@ -1594,7 +1594,7 @@ template _Alloc_ptr_t<_Alloc> _Uninitialized_copy_al_unchecked( const _InIt _First, const _InIt _Last, const _Alloc_ptr_t<_Alloc> _Dest, _Alloc&, true_type) { // copy [_First, _Last) to raw _Dest, using default _Alloc construct, memmove optimization - return _Copy_memmove(_First, _Last, _Unfancy(_Dest)); + return _Memmove_forward(_First, _Last, _Unfancy(_Dest)); } template @@ -1625,7 +1625,7 @@ _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrow const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast)); if constexpr (_Memmove_in_uninitialized_copy_is_safe) { - _UDest = _Copy_memmove(_UFirst, _ULast, _UDest); + _UDest = _Memmove_forward(_UFirst, _ULast, _UDest); } else { _Uninitialized_backout _Backout{_UDest}; for (; _UFirst != _ULast; ++_UFirst) { @@ -1654,7 +1654,7 @@ template _NoThrowFwdIt _Uninitialized_copy_unchecked( const _InIt _First, const _InIt _Last, const _NoThrowFwdIt _Dest, true_type) { // copy [_First, _Last) to raw [_Dest, ...), memmove optimization - return _Copy_memmove(_First, _Last, _Dest); + return _Memmove_forward(_First, _Last, _Dest); } template @@ -1683,7 +1683,7 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_move( const auto _ULast = _Get_unwrapped(_Last); if constexpr (conjunction_v>, _Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>>) { - _Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest)); + _Memmove_forward(_UFirst, _ULast, _Unfancy(_Dest)); return _Dest + (_ULast - _UFirst); } else { _Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al}; @@ -1711,7 +1711,7 @@ template _Alloc_ptr_t<_Alloc> _Uninitialized_move_al_unchecked( const _InIt _First, const _InIt _Last, _Alloc_ptr_t<_Alloc> _Dest, _Alloc&, true_type) { // move [_First, _Last) to raw _Dest, using default _Alloc construct, memmove optimization - _Copy_memmove(_First, _Last, _Unfancy(_Dest)); + _Memmove_forward(_First, _Last, _Unfancy(_Dest)); return _Dest + (_Last - _First); } diff --git a/stl/inc/xutility b/stl/inc/xutility index 4d5903e200..0ac84fcee8 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4408,7 +4408,7 @@ _INLINE_VAR constexpr bool _Memmove_in_uninitialized_move_is_safe = _Can_memop, _IterDest, _Memop_cat::_Move_uninitialized>; template -_OutIt _Copy_memmove(_InIt _First, _InIt _Last, _OutIt _Dest) { +_OutIt _Memmove_forward(_InIt _First, _InIt _Last, _OutIt _Dest) { const char* const _First_ch = const_cast(reinterpret_cast(_First)); const char* const _Last_ch = const_cast(reinterpret_cast(_Last)); char* const _Dest_ch = const_cast(reinterpret_cast(_Dest)); @@ -4418,18 +4418,18 @@ _OutIt _Copy_memmove(_InIt _First, _InIt _Last, _OutIt _Dest) { } template -_OutIt _Copy_memmove(move_iterator<_InIt> _First, move_iterator<_InIt> _Last, _OutIt _Dest) { - return _Copy_memmove(_First.base(), _Last.base(), _Dest); +_OutIt _Memmove_forward(move_iterator<_InIt> _First, move_iterator<_InIt> _Last, _OutIt _Dest) { + return _Memmove_forward(_First.base(), _Last.base(), _Dest); } template -_OutIt _Copy_memcpy_common(_InIt _IFirst, _InIt _ILast, _OutIt _OFirst, _OutIt _OLast) noexcept { +_OutIt _Memmove_forward_common(_InIt _IFirst, _InIt _ILast, _OutIt _OFirst, _OutIt _OLast) noexcept { const auto _IFirst_ch = const_cast(reinterpret_cast(_IFirst)); const auto _ILast_ch = const_cast(reinterpret_cast(_ILast)); const auto _OFirst_ch = const_cast(reinterpret_cast(_OFirst)); const auto _OLast_ch = const_cast(reinterpret_cast(_OLast)); const auto _Count = static_cast((_STD min)(_ILast_ch - _IFirst_ch, _OLast_ch - _OFirst_ch)); - _CSTD memcpy(_OFirst_ch, _IFirst_ch, _Count); + _CSTD memmove(_OFirst_ch, _IFirst_ch, _Count); return reinterpret_cast<_OutIt>(_OFirst_ch + _Count); } @@ -4447,7 +4447,7 @@ _CONSTEXPR20 _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated { - return _Copy_memmove(_First, _Last, _Dest); + return _Memmove_forward(_First, _Last, _Dest); } } @@ -4471,7 +4471,7 @@ _OutIt _Copy_unchecked1(_InIt _First, _InIt _Last, _OutIt _Dest, false_type) { template _OutIt _Copy_unchecked1(_InIt _First, _InIt _Last, _OutIt _Dest, true_type) { // copy [_First, _Last) to [_Dest, ...), pointers to trivially copyable - return _Copy_memmove(_First, _Last, _Dest); + return _Memmove_forward(_First, _Last, _Dest); } template @@ -4517,7 +4517,7 @@ _CONSTEXPR20 _OutIt copy_n(_InIt _First, _Diff _Count_raw, _OutIt _Dest) { if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated { - _UDest = _Copy_memmove(_UFirst, _UFirst + _Count, _UDest); + _UDest = _Memmove_forward(_UFirst, _UFirst + _Count, _UDest); _Seek_wrapped(_Dest, _UDest); return _Dest; } @@ -4563,7 +4563,7 @@ template _OutIt _Copy_n_unchecked4(_InIt _First, _Diff _Count, _OutIt _Dest, true_type) { // copy [_First, _First + _Count) to [_Dest, ...), memmove optimization // pre: 0 < _Count - return _Copy_memmove(_First, _First + _Count, _Dest); + return _Memmove_forward(_First, _First + _Count, _Dest); } template @@ -4593,7 +4593,7 @@ _FwdIt2 copy_n(_ExPo&&, _FwdIt1 _First, _Diff _Count_raw, _FwdIt2 _Dest) noexcep // FUNCTION TEMPLATE copy_backward template -_BidIt2 _Copy_backward_memmove(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { +_BidIt2 _Memmove_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // implement copy_backward-like function as memmove const char* const _First_ch = const_cast(reinterpret_cast(_First)); const char* const _Last_ch = const_cast(reinterpret_cast(_Last)); @@ -4603,8 +4603,8 @@ _BidIt2 _Copy_backward_memmove(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { } template -_BidIt2 _Copy_backward_memmove(move_iterator<_BidIt1> _First, move_iterator<_BidIt1> _Last, _BidIt2 _Dest) { - return _Copy_backward_memmove(_First.base(), _Last.base(), _Dest); +_BidIt2 _Memmove_backward(move_iterator<_BidIt1> _First, move_iterator<_BidIt1> _Last, _BidIt2 _Dest) { + return _Memmove_backward(_First.base(), _Last.base(), _Dest); } #if _HAS_IF_CONSTEXPR @@ -4616,7 +4616,7 @@ _NODISCARD _CONSTEXPR20 _BidIt2 _Copy_backward_unchecked(_BidIt1 _First, _BidIt1 if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated { - return _Copy_backward_memmove(_First, _Last, _Dest); + return _Memmove_backward(_First, _Last, _Dest); } } @@ -4651,7 +4651,7 @@ _BidIt2 _Copy_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest, f template _BidIt2 _Copy_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest, true_type) { // copy [_First, _Last) backwards to [..., _Dest), memmove optimization - return _Copy_backward_memmove(_First, _Last, _Dest); + return _Memmove_backward(_First, _Last, _Dest); } template @@ -4686,7 +4686,7 @@ _CONSTEXPR20 _OutIt _Move_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated { - return _Copy_memmove(_First, _Last, _Dest); + return _Memmove_forward(_First, _Last, _Dest); } } @@ -4710,7 +4710,7 @@ _OutIt _Move_unchecked1(_InIt _First, _InIt _Last, _OutIt _Dest, false_type) { template _OutIt _Move_unchecked1(_InIt _First, _InIt _Last, _OutIt _Dest, true_type) { // move [_First, _Last) to [_Dest, ...), memmove optimization - return _Copy_memmove(_First, _Last, _Dest); + return _Memmove_forward(_First, _Last, _Dest); } template @@ -4754,7 +4754,7 @@ _CONSTEXPR20 _BidIt2 _Move_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _Bi if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated { - return _Copy_backward_memmove(_First, _Last, _Dest); + return _Memmove_backward(_First, _Last, _Dest); } } @@ -4778,7 +4778,7 @@ _BidIt2 _Move_backward_unchecked1(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest, template _BidIt2 _Move_backward_unchecked1(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest, true_type) { // move [_First, _Last) backwards to [..., _Dest), memmove optimization - return _Copy_backward_memmove(_First, _Last, _Dest); + return _Memmove_backward(_First, _Last, _Dest); } template From a3e3dc864a08258ca724c1f429b49bef24fbdea8 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Mon, 5 Oct 2020 22:19:30 +0200 Subject: [PATCH 6/8] Implement constexpr versions of the meow_memmove helpers --- stl/inc/memory | 16 -- stl/inc/xmemory | 62 +++++--- stl/inc/xutility | 19 ++- tests/std/test.lst | 1 + .../tests/P0784R7_library_machinery/env.lst | 4 + .../tests/P0784R7_library_machinery/test.cpp | 141 ++++++++++++++++++ 6 files changed, 203 insertions(+), 40 deletions(-) create mode 100644 tests/std/tests/P0784R7_library_machinery/env.lst create mode 100644 tests/std/tests/P0784R7_library_machinery/test.cpp diff --git a/stl/inc/memory b/stl/inc/memory index bc16c897de..d49d6f5da6 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -545,22 +545,7 @@ namespace ranges { }; inline constexpr _Uninitialized_fill_n_fn uninitialized_fill_n{_Not_quite_object::_Construct_tag{}}; -} // namespace ranges -#endif // __cpp_lib_concepts -// FUNCTION TEMPLATE construct_at -#if _HAS_CXX20 -template -_CONSTEXPR20_DYNALLOC auto construct_at(_Ty* const _Location, _Types&&... _Args) noexcept( - noexcept(::new (const_cast(static_cast(_Location))) - _Ty(_STD forward<_Types>(_Args)...))) // strengthened - -> decltype( - ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...)) { - return ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...); -} - -#ifdef __cpp_lib_concepts -namespace ranges { // VARIABLE ranges::construct_at class _Construct_at_fn : private _Not_quite_object { public: @@ -583,7 +568,6 @@ namespace ranges { inline constexpr _Construct_at_fn construct_at{_Not_quite_object::_Construct_tag{}}; } // namespace ranges #endif // __cpp_lib_concepts -#endif // _HAS_CXX20 #if _HAS_CXX17 // FUNCTION TEMPLATE destroy_at diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 19bcb23411..be828abe29 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1424,18 +1424,18 @@ struct _Uninitialized_backout { // struct to undo partially constructed ranges i _Uninitialized_backout(const _Uninitialized_backout&) = delete; _Uninitialized_backout& operator=(const _Uninitialized_backout&) = delete; - ~_Uninitialized_backout() { + _CONSTEXPR20_DYNALLOC ~_Uninitialized_backout() { _Destroy_range(_First, _Last); } template - void _Emplace_back(_Types&&... _Vals) { + _CONSTEXPR20_DYNALLOC void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment _Construct_in_place(*_Last, _STD forward<_Types>(_Vals)...); ++_Last; } - _NoThrowFwdIt _Release() { // suppress any exception handling backout and return _Last + constexpr _NoThrowFwdIt _Release() { // suppress any exception handling backout and return _Last _First = _Last; return _Last; } @@ -1478,18 +1478,23 @@ namespace ranges { // FUNCTION TEMPLATE _Uninitialized_move_unchecked #if _HAS_IF_CONSTEXPR template -_NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { +_CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_move_unchecked( + _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // move [_First, _Last) to raw [_Dest, ...) if constexpr (_Memmove_in_uninitialized_move_is_safe<_InIt, _NoThrowFwdIt>) { - return _Memmove_forward(_First, _Last, _Dest); - } else { - _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; - for (; _First != _Last; ++_First) { - _Backout._Emplace_back(_STD move(*_First)); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + return _Memmove_forward(_First, _Last, _Dest); } - - return _Backout._Release(); } + _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; + for (; _First != _Last; ++_First) { + _Backout._Emplace_back(_STD move(*_First)); + } + + return _Backout._Release(); } #else // ^^^ _HAS_IF_CONSTEXPR ^^^ // vvv !_HAS_IF_CONSTEXPR vvv template @@ -1617,6 +1622,28 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy( // FUNCTION TEMPLATE uninitialized_copy #if _HAS_IF_CONSTEXPR +template +_CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_copy_unchecked( + _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { + // copy [_First, _Last) to raw [_Dest, ...) + if constexpr (_Memmove_in_uninitialized_copy_is_safe<_InIt, _NoThrowFwdIt>) { +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + return _Memmove_forward(_First, _Last, _Dest); + } + } + _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; + for (; _First != _Last; ++_First) { + _Backout._Emplace_back(*_First); + } + + _Dest = _Backout._Release(); + + return _Dest; +} + template _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) { // copy [_First, _Last) to raw [_Dest, ...) @@ -1624,18 +1651,7 @@ _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrow auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast)); - if constexpr (_Memmove_in_uninitialized_copy_is_safe) { - _UDest = _Memmove_forward(_UFirst, _ULast, _UDest); - } else { - _Uninitialized_backout _Backout{_UDest}; - for (; _UFirst != _ULast; ++_UFirst) { - _Backout._Emplace_back(*_UFirst); - } - - _UDest = _Backout._Release(); - } - - _Seek_wrapped(_Dest, _UDest); + _Seek_wrapped(_Dest, _Uninitialized_copy_unchecked(_UFirst, _ULast, _UDest)); return _Dest; } #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv diff --git a/stl/inc/xutility b/stl/inc/xutility index 0ac84fcee8..a9e6099d12 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -119,11 +119,28 @@ struct _Get_rebind_alias<_Ty, _Other, void_t; }; +// FUNCTION TEMPLATE construct_at +#if _HAS_CXX20 +template +_CONSTEXPR20_DYNALLOC auto construct_at(_Ty* const _Location, _Types&&... _Args) noexcept( + noexcept(::new (const_cast(static_cast(_Location))) + _Ty(_STD forward<_Types>(_Args)...))) // strengthened + -> decltype( + ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...)) { + return ::new (const_cast(static_cast(_Location))) _Ty(_STD forward<_Types>(_Args)...); +} +#endif // _HAS_CXX20 + // FUNCTION TEMPLATE _Construct_in_place template -void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) { +_CONSTEXPR20_DYNALLOC void _Construct_in_place(_Ty& _Obj, _Types&&... _Args) noexcept( + is_nothrow_constructible_v<_Ty, _Types...>) { +#if _HAS_CXX20 + _STD construct_at(_STD addressof(_Obj), _STD forward<_Types>(_Args)...); +#else // ^^^_HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv ::new (const_cast(static_cast(_STD addressof(_Obj)))) _Ty(_STD forward<_Types>(_Args)...); +#endif // !_HAS_CXX20 } // STRUCT TEMPLATE pointer_traits diff --git a/tests/std/test.lst b/tests/std/test.lst index c681576094..08bb5af506 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -246,6 +246,7 @@ tests\P0718R2_atomic_smart_ptrs tests\P0758R1_is_nothrow_convertible tests\P0768R1_spaceship_operator tests\P0769R2_shift_left_shift_right +tests\P0784R7_library_machinery tests\P0784R7_library_support_for_more_constexpr_containers tests\P0811R3_midpoint_lerp tests\P0896R4_common_iterator diff --git a/tests/std/tests/P0784R7_library_machinery/env.lst b/tests/std/tests/P0784R7_library_machinery/env.lst new file mode 100644 index 0000000000..642f530ffa --- /dev/null +++ b/tests/std/tests/P0784R7_library_machinery/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P0784R7_library_machinery/test.cpp b/tests/std/tests/P0784R7_library_machinery/test.cpp new file mode 100644 index 0000000000..a1aa0d52a5 --- /dev/null +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -0,0 +1,141 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include + +#pragma warning(disable : 4582) // '%s': constructor is not implicitly called +#pragma warning(disable : 4583) // '%s': destructor is not implicitly called + +using namespace std; + +struct int_wrapper_copy { + constexpr int_wrapper_copy() = default; + constexpr int_wrapper_copy(const int v) : _val(v){}; + + constexpr int_wrapper_copy(const int_wrapper_copy& other) : _val(other._val) {} + constexpr int_wrapper_copy& operator=(const int_wrapper_copy& other) { + _val = other._val; + return *this; + } + + constexpr int_wrapper_copy(int_wrapper_copy&&) = delete; + constexpr int_wrapper_copy& operator=(int_wrapper_copy&&) = delete; + + constexpr bool operator==(const int_wrapper_copy&) const = default; + + int _val = 0; +}; + +struct int_wrapper_move { + constexpr int_wrapper_move() = default; + constexpr int_wrapper_move(const int v) : _val(v){}; + + constexpr int_wrapper_move(const int_wrapper_move&) = delete; + constexpr int_wrapper_move& operator=(const int_wrapper_move&) = delete; + + constexpr int_wrapper_move(int_wrapper_move&& other) : _val(exchange(other._val, -1)) {} + constexpr int_wrapper_move& operator=(int_wrapper_move&& other) { + _val = exchange(other._val, -1); + return *this; + } + + constexpr bool operator==(const int_wrapper_move&) const = default; + + int _val = 0; +}; + +static constexpr int_wrapper_copy expected_copy[] = {1, 2, 3, 4}; +static constexpr int_wrapper_move expected_move[] = {1, 2, 3, 4}; +static constexpr int_wrapper_move expected_after_move[] = {-1, -1, -1, -1}; + +constexpr bool test() { + { // _Copy_unchecked + int_wrapper_copy input[] = {1, 2, 3, 4}; + int_wrapper_copy output[4] = {5, 6, 7, 8}; + + const same_as auto result = _Copy_unchecked(begin(input), end(input), begin(output)); + assert(result == end(output)); + assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); + } + + { // _Copy_backward_unchecked + int_wrapper_copy input[] = {1, 2, 3, 4}; + int_wrapper_copy output[4] = {5, 6, 7, 8}; + + const same_as auto result = _Copy_backward_unchecked(begin(input), end(input), end(output)); + assert(result == begin(output)); + assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); + } + +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) + { // _Uninitialized_copy_unchecked + int_wrapper_copy input[] = {1, 2, 3, 4}; + int_wrapper_copy output[4]; + + const same_as auto result = + _Uninitialized_copy_unchecked(begin(input), end(input), begin(output)); + assert(result == end(output)); + assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); + } +#endif // _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) + + { // _Move_unchecked + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4] = {5, 6, 7, 8}; + + const same_as auto result = _Move_unchecked(begin(input), end(input), begin(output)); + assert(result == end(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } + + { // _Move_backward_unchecked + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4] = {5, 6, 7, 8}; + + const same_as auto result = _Move_backward_unchecked(begin(input), end(input), end(output)); + assert(result == begin(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } + + { // _Move_backward_common + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4] = {5, 6, 7, 8}; + + const same_as auto result = + ranges::_Move_backward_common(begin(input), end(input), end(output)); + assert(result == begin(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } + +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) + { // _Uninitialized_move_unchecked + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4]; + + const same_as auto result = + _Uninitialized_move_unchecked(begin(input), end(input), begin(output)); + assert(result == end(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } +#endif // _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) + return true; +} + +int main() { + test(); + static_assert(test()); +} From 67887e51f8a33c746025809b326e04e423761633 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Wed, 14 Oct 2020 12:01:35 +0200 Subject: [PATCH 7/8] Not in concepts land --- .../tests/P0784R7_library_machinery/test.cpp | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/std/tests/P0784R7_library_machinery/test.cpp b/tests/std/tests/P0784R7_library_machinery/test.cpp index a1aa0d52a5..519cfb7da9 100644 --- a/tests/std/tests/P0784R7_library_machinery/test.cpp +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -55,7 +55,8 @@ constexpr bool test() { int_wrapper_copy input[] = {1, 2, 3, 4}; int_wrapper_copy output[4] = {5, 6, 7, 8}; - const same_as auto result = _Copy_unchecked(begin(input), end(input), begin(output)); + const auto result = _Copy_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_copy*>); assert(result == end(output)); assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); } @@ -64,7 +65,8 @@ constexpr bool test() { int_wrapper_copy input[] = {1, 2, 3, 4}; int_wrapper_copy output[4] = {5, 6, 7, 8}; - const same_as auto result = _Copy_backward_unchecked(begin(input), end(input), end(output)); + const auto result = _Copy_backward_unchecked(begin(input), end(input), end(output)); + static_assert(is_same_v, int_wrapper_copy*>); assert(result == begin(output)); assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); } @@ -74,8 +76,8 @@ constexpr bool test() { int_wrapper_copy input[] = {1, 2, 3, 4}; int_wrapper_copy output[4]; - const same_as auto result = - _Uninitialized_copy_unchecked(begin(input), end(input), begin(output)); + const auto result = _Uninitialized_copy_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_copy*>); assert(result == end(output)); assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); } @@ -85,7 +87,8 @@ constexpr bool test() { int_wrapper_move input[] = {1, 2, 3, 4}; int_wrapper_move output[4] = {5, 6, 7, 8}; - const same_as auto result = _Move_unchecked(begin(input), end(input), begin(output)); + const auto result = _Move_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_move*>); assert(result == end(output)); assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); if (is_constant_evaluated()) { @@ -97,7 +100,8 @@ constexpr bool test() { int_wrapper_move input[] = {1, 2, 3, 4}; int_wrapper_move output[4] = {5, 6, 7, 8}; - const same_as auto result = _Move_backward_unchecked(begin(input), end(input), end(output)); + const auto result = _Move_backward_unchecked(begin(input), end(input), end(output)); + static_assert(is_same_v, int_wrapper_move*>); assert(result == begin(output)); assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); if (is_constant_evaluated()) { @@ -109,8 +113,8 @@ constexpr bool test() { int_wrapper_move input[] = {1, 2, 3, 4}; int_wrapper_move output[4] = {5, 6, 7, 8}; - const same_as auto result = - ranges::_Move_backward_common(begin(input), end(input), end(output)); + const auto result = ranges::_Move_backward_common(begin(input), end(input), end(output)); + static_assert(is_same_v, int_wrapper_move*>); assert(result == begin(output)); assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); if (is_constant_evaluated()) { @@ -123,8 +127,8 @@ constexpr bool test() { int_wrapper_move input[] = {1, 2, 3, 4}; int_wrapper_move output[4]; - const same_as auto result = - _Uninitialized_move_unchecked(begin(input), end(input), begin(output)); + const auto result = _Uninitialized_move_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_move*>); assert(result == end(output)); assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); if (is_constant_evaluated()) { From bd5690791ada0aa7f6e990acdca99f21f240d843 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Wed, 14 Oct 2020 15:51:54 +0200 Subject: [PATCH 8/8] Guard ranges stuff... --- tests/std/tests/P0784R7_library_machinery/test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/std/tests/P0784R7_library_machinery/test.cpp b/tests/std/tests/P0784R7_library_machinery/test.cpp index 519cfb7da9..583cfd1bf9 100644 --- a/tests/std/tests/P0784R7_library_machinery/test.cpp +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -109,6 +109,7 @@ constexpr bool test() { } } +#ifdef __cpp_lib_concepts { // _Move_backward_common int_wrapper_move input[] = {1, 2, 3, 4}; int_wrapper_move output[4] = {5, 6, 7, 8}; @@ -121,6 +122,7 @@ constexpr bool test() { assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); } } +#endif // __cpp_lib_concepts #if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) { // _Uninitialized_move_unchecked