Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -4452,6 +4452,7 @@ _EXPORT_STD template <class _InIt, class _OutIt, class _Ty>
_CONSTEXPR20 _OutIt replace_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Oldval, const _Ty& _Newval) {
// copy replacing each matching _Oldval with _Newval
_STD _Adl_verify_range(_First, _Last);
_STD _Verify_ranges_do_not_overlap(_First, _Last, _Dest);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_InIt>(_UFirst, _ULast));
Expand Down Expand Up @@ -4500,7 +4501,7 @@ namespace ranges {
auto _UFirst = _RANGES _Unwrap_iter<_Se>(_STD move(_First));
auto _ULast = _RANGES _Unwrap_sent<_It>(_STD move(_Last));
const auto _Count = _RANGES _Idl_distance<_It>(_UFirst, _ULast);
auto _UResult = _Replace_copy_unchecked(_STD move(_UFirst), _STD move(_ULast),
auto _UResult = _Replace_copy_common(_STD move(_UFirst), _STD move(_ULast),
_STD _Get_unwrapped_n(_STD move(_Output), _Count), _Oldval, _Newval, _STD _Pass_fn(_Proj));

_STD _Seek_wrapped(_First, _STD move(_UResult.in));
Expand All @@ -4515,8 +4516,8 @@ namespace ranges {
_Out _Output, const _Ty1& _Oldval, const _Ty2& _Newval, _Pj _Proj = {}) _CONST_CALL_OPERATOR {
const auto _Count = _RANGES _Idl_distance(_Range);
auto _First = _RANGES begin(_Range);
auto _UResult = _Replace_copy_unchecked(_RANGES _Unwrap_range_iter<_Rng>(_STD move(_First)), _Uend(_Range),
_STD _Get_unwrapped_n(_STD move(_Output), _Count), _Oldval, _Newval, _STD _Pass_fn(_Proj));
auto _UResult = _Replace_copy_common(_RANGES _Unwrap_range_iter<_Rng>(_STD move(_First)), _Uend(_Range),
_STD _Get_unwrapped_n(_STD move(_Output), _Count), _Oldval, _Newval, _STD _Pass_fn(_Proj));

_STD _Seek_wrapped(_First, _STD move(_UResult.in));
_STD _Seek_wrapped(_Output, _STD move(_UResult.out));
Expand All @@ -4525,7 +4526,7 @@ namespace ranges {

private:
template <class _It, class _Se, class _Ty1, class _Ty2, class _Out, class _Pj>
_NODISCARD static constexpr replace_copy_result<_It, _Out> _Replace_copy_unchecked(
_NODISCARD static constexpr replace_copy_result<_It, _Out> _Replace_copy_common(
_It _First, const _Se _Last, _Out _Output, const _Ty1& _Oldval, const _Ty2& _Newval, _Pj _Proj) {
// copy [_First, _Last) to _Output while replacing projected _Oldval with _Newval
_STL_INTERNAL_STATIC_ASSERT(input_iterator<_It>);
Expand All @@ -4534,6 +4535,8 @@ namespace ranges {
_STL_INTERNAL_STATIC_ASSERT(indirectly_copyable<_It, _Out>);
_STL_INTERNAL_STATIC_ASSERT(indirect_binary_predicate<equal_to, projected<_It, _Pj>, const _Ty1*>);

_STD _Verify_ranges_do_not_overlap(_First, _Last, _Output);
Comment thread
AlexGuteniev marked this conversation as resolved.

for (; _First != _Last; ++_First, (void) ++_Output) {
if constexpr (_Can_vectorize_replace_copy<_Out, iter_value_t<_It>, _Ty2>) {
*_Output = _STD invoke(_Proj, *_First) == _Oldval ? _Newval : *_First;
Expand All @@ -4558,6 +4561,7 @@ _EXPORT_STD template <class _InIt, class _OutIt, class _Pr, class _Ty>
_CONSTEXPR20 _OutIt replace_copy_if(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pred, const _Ty& _Val) {
// copy replacing each satisfying _Pred with _Val
_STD _Adl_verify_range(_First, _Last);
_STD _Verify_ranges_do_not_overlap(_First, _Last, _Dest);
auto _UFirst = _STD _Get_unwrapped(_First);
const auto _ULast = _STD _Get_unwrapped(_Last);
auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_InIt>(_UFirst, _ULast));
Expand Down Expand Up @@ -4607,7 +4611,7 @@ namespace ranges {
auto _ULast = _RANGES _Unwrap_sent<_It>(_STD move(_Last));
const auto _Count = _RANGES _Idl_distance<_It>(_UFirst, _ULast);

auto _UResult = _Replace_copy_if_unchecked(_STD move(_UFirst), _STD move(_ULast),
auto _UResult = _Replace_copy_if_common(_STD move(_UFirst), _STD move(_ULast),
_STD _Get_unwrapped_n(_STD move(_Output), _Count), _STD _Pass_fn(_Pred), _Newval, _STD _Pass_fn(_Proj));

_STD _Seek_wrapped(_First, _STD move(_UResult.in));
Expand All @@ -4622,9 +4626,8 @@ namespace ranges {
_Rng&& _Range, _Out _Output, _Pr _Pred, const _Ty& _Newval, _Pj _Proj = {}) _CONST_CALL_OPERATOR {
const auto _Count = _RANGES _Idl_distance(_Range);
auto _First = _RANGES begin(_Range);
auto _UResult = _Replace_copy_if_unchecked(_RANGES _Unwrap_range_iter<_Rng>(_STD move(_First)),
_Uend(_Range), _STD _Get_unwrapped_n(_STD move(_Output), _Count), _STD _Pass_fn(_Pred), _Newval,
_STD _Pass_fn(_Proj));
auto _UResult = _Replace_copy_if_common(_RANGES _Unwrap_range_iter<_Rng>(_STD move(_First)), _Uend(_Range),
_STD _Get_unwrapped_n(_STD move(_Output), _Count), _STD _Pass_fn(_Pred), _Newval, _STD _Pass_fn(_Proj));

_STD _Seek_wrapped(_First, _STD move(_UResult.in));
_STD _Seek_wrapped(_Output, _STD move(_UResult.out));
Expand All @@ -4633,7 +4636,7 @@ namespace ranges {

private:
template <class _It, class _Se, class _Ty, class _Out, class _Pj, class _Pr>
_NODISCARD static constexpr replace_copy_if_result<_It, _Out> _Replace_copy_if_unchecked(
_NODISCARD static constexpr replace_copy_if_result<_It, _Out> _Replace_copy_if_common(
_It _First, const _Se _Last, _Out _Output, _Pr _Pred, const _Ty& _Newval, _Pj _Proj) {
// copy [_First, _Last) to _Output while replacing _Oldval with _Newval if projected _Oldval fulfills _Pred
_STL_INTERNAL_STATIC_ASSERT(input_iterator<_It>);
Expand All @@ -4642,6 +4645,8 @@ namespace ranges {
_STL_INTERNAL_STATIC_ASSERT(indirectly_copyable<_It, _Out>);
_STL_INTERNAL_STATIC_ASSERT(indirect_unary_predicate<_Pr, projected<_It, _Pj>>);

_STD _Verify_ranges_do_not_overlap(_First, _Last, _Output);

for (; _First != _Last; ++_First, (void) ++_Output) {
if constexpr (_Can_vectorize_replace_copy<_Out, iter_value_t<_It>, _Ty>) {
*_Output = _STD invoke(_Pred, _STD invoke(_Proj, *_First)) ? _Newval : *_First;
Expand Down Expand Up @@ -5615,6 +5620,7 @@ _EXPORT_STD template <class _BidIt, class _OutIt>
_CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) {
// copy reversing elements in [_First, _Last)
_STD _Adl_verify_range(_First, _Last);
_STD _Verify_ranges_do_not_overlap(_First, _Last, _Dest);
const auto _UFirst = _STD _Get_unwrapped(_First);
auto _ULast = _STD _Get_unwrapped(_Last);
auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_BidIt>(_UFirst, _ULast));
Expand Down Expand Up @@ -5706,6 +5712,8 @@ namespace ranges {
_STL_INTERNAL_STATIC_ASSERT(weakly_incrementable<_Out>);
_STL_INTERNAL_STATIC_ASSERT(indirectly_copyable<_It, _Out>);

_STD _Verify_ranges_do_not_overlap(_First, _Last, _Output);

#if _USE_STD_VECTOR_ALGORITHMS
if constexpr (contiguous_iterator<_It> && contiguous_iterator<_Out>) {
using _Elem = remove_reference_t<iter_reference_t<_It>>;
Expand Down Expand Up @@ -5851,6 +5859,7 @@ _CONSTEXPR20 _OutIt rotate_copy(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last, _OutIt
// copy rotating [_First, _Last)
_STD _Adl_verify_range(_First, _Mid);
_STD _Adl_verify_range(_Mid, _Last);
_STD _Verify_ranges_do_not_overlap(_First, _Last, _Dest);
const auto _UFirst = _STD _Get_unwrapped(_First);
const auto _UMid = _STD _Get_unwrapped(_Mid);
const auto _ULast = _STD _Get_unwrapped(_Last);
Expand Down Expand Up @@ -5886,7 +5895,7 @@ namespace ranges {
auto _UFirst = _RANGES _Unwrap_iter<_Se>(_STD move(_First));
auto _ULast = _RANGES _Unwrap_sent<_It>(_STD move(_Last));
const auto _Count = _RANGES _Idl_distance<_It>(_UFirst, _ULast);
auto _UResult = _Rotate_copy_unchecked(_STD move(_UFirst), _RANGES _Unwrap_iter<_Se>(_STD move(_Mid)),
auto _UResult = _Rotate_copy_common(_STD move(_UFirst), _RANGES _Unwrap_iter<_Se>(_STD move(_Mid)),
_STD move(_ULast), _STD _Get_unwrapped_n(_STD move(_Output), _Count));

_STD _Seek_wrapped(_First, _STD move(_UResult.in));
Expand All @@ -5901,22 +5910,24 @@ namespace ranges {
_STD _Adl_verify_range(_RANGES begin(_Range), _Mid);
_STD _Adl_verify_range(_Mid, _RANGES end(_Range));
const auto _Count = _RANGES _Idl_distance(_Range);
auto _UResult = _Rotate_copy_unchecked(_Ubegin(_Range), _RANGES _Unwrap_range_iter<_Rng>(_STD move(_Mid)),
_Uend(_Range), _STD _Get_unwrapped_n(_STD move(_Output), _Count));
auto _UResult = _Rotate_copy_common(_Ubegin(_Range), _RANGES _Unwrap_range_iter<_Rng>(_STD move(_Mid)),
_Uend(_Range), _STD _Get_unwrapped_n(_STD move(_Output), _Count));
_STD _Seek_wrapped(_Output, _STD move(_UResult.out));
return {_RANGES _Rewrap_iterator(_Range, _STD move(_UResult.in)), _STD move(_Output)};
}

private:
template <class _It, class _Se, class _Out>
_NODISCARD static constexpr rotate_copy_result<_It, _Out> _Rotate_copy_unchecked(
_NODISCARD static constexpr rotate_copy_result<_It, _Out> _Rotate_copy_common(
_It _First, _It _Mid, _Se _Last, _Out _Output) {
// Copy the content of [_Mid, _Last) and [_First, _Mid) to _Output
_STL_INTERNAL_STATIC_ASSERT(forward_iterator<_It>);
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>);
_STL_INTERNAL_STATIC_ASSERT(weakly_incrementable<_Out>);
_STL_INTERNAL_STATIC_ASSERT(indirectly_copyable<_It, _Out>);

_STD _Verify_ranges_do_not_overlap(_First, _Last, _Output);

auto _UResult1 = _RANGES _Copy_unchecked(_Mid, _STD move(_Last), _STD move(_Output));
auto _UResult2 = _RANGES _Copy_unchecked(_STD move(_First), _STD move(_Mid), _STD move(_UResult1.out));
return {_STD move(_UResult1.in), _STD move(_UResult2.out)};
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ tests\GH_005276_system_error_heap_use_after_free
tests\GH_005315_destructor_tombstones
tests\GH_005402_string_with_volatile_range
tests\GH_005421_vector_algorithms_integer_class_type_iterator
tests\GH_005472_do_not_overlap
tests\LWG2381_num_get_floating_point
tests\LWG2597_complex_branch_cut
tests\LWG3018_shared_ptr_function
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/GH_005472_do_not_overlap/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_matrix.lst
41 changes: 41 additions & 0 deletions tests/std/tests/GH_005472_do_not_overlap/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <algorithm>
#include <ranges>

#include <test_death.hpp>

using namespace std;

int arr[3] = {};

int main(int argc, char* argv[]) {
#if _ITERATOR_DEBUG_LEVEL == 2
std_testing::death_test_executive exec;

exec.add_death_tests({
+[] { swap_ranges(arr, arr + 2, arr + 1); },
+[] { reverse_copy(arr, arr + 2, arr + 1); },
+[] { replace_copy(arr, arr + 2, arr + 1, 1, 2); },
+[] { replace_copy_if(arr, arr + 2, arr + 1, [](int) { return false; }, 2); },
+[] { rotate_copy(arr, arr + 1, arr + 2, arr + 1); },
#if _HAS_CXX20
+[] { ranges::reverse_copy(arr, arr + 2, arr + 1); },
+[] { ranges::reverse_copy(ranges::subrange(arr, arr + 2), arr + 1); },
Comment thread
StephanTLavavej marked this conversation as resolved.
+[] { ranges::replace_copy(arr, arr + 2, arr + 1, 1, 2); },
+[] { ranges::replace_copy(ranges::subrange(arr, arr + 2), arr + 1, 1, 2); },
+[] { ranges::replace_copy_if(arr, arr + 2, arr + 1, [](int) { return false; }, 2); },
+[] { ranges::replace_copy_if(ranges::subrange(arr, arr + 2), arr + 1, [](int) { return false; }, 2); },
+[] { ranges::rotate_copy(arr, arr + 1, arr + 2, arr + 1); },
+[] { ranges::rotate_copy(ranges::subrange(arr, arr + 2), arr + 1, arr + 1); },
#endif // _HAS_CXX20
});

return exec.run(argc, argv);
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL != 2 vvv
(void) argc;
(void) argv;
return 0; // This test is only for iterator debug mode
#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 2 ^^^
}