зеркало из https://github.com/microsoft/STL.git
Родитель
eb33f1a1e9
Коммит
af3db68781
|
@ -6128,7 +6128,7 @@ _CONSTEXPR20 void _Push_heap_by_index(
|
|||
_Hole = _Idx;
|
||||
}
|
||||
|
||||
*(_First + _Hole) = _STD move(_Val); // drop _Val into final hole
|
||||
*(_First + _Hole) = _STD forward<_Ty>(_Val); // drop _Val into final hole
|
||||
}
|
||||
|
||||
template <class _RanIt, class _Pr>
|
||||
|
@ -6154,16 +6154,17 @@ _CONSTEXPR20 void push_heap(_RanIt _First, _RanIt _Last) {
|
|||
#ifdef __cpp_lib_concepts
|
||||
namespace ranges {
|
||||
// VARIABLE ranges::push_heap
|
||||
template <class _It, class _Pr, class _Pj>
|
||||
// clang-format off
|
||||
template <random_access_iterator _It, class _Ty, class _Pr, class _Pj1, class _Pj2>
|
||||
requires sortable<_It, _Pr, _Pj1> && indirectly_writable<_It, _Ty>
|
||||
&& indirect_strict_weak_order<_Pr, projected<_It, _Pj1>, projected<remove_reference_t<_Ty>*, _Pj2>>
|
||||
constexpr void _Push_heap_by_index(const _It _First, iter_difference_t<_It> _Hole,
|
||||
const iter_difference_t<_It> _Top, iter_value_t<_It>&& _Val, _Pr _Pred, _Pj _Proj) {
|
||||
const iter_difference_t<_It> _Top, _Ty&& _Val, _Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) {
|
||||
// clang-format on
|
||||
// percolate _Hole to _Top or where _Val belongs
|
||||
_STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>);
|
||||
_STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>);
|
||||
|
||||
while (_Top < _Hole) {
|
||||
const auto _Idx = static_cast<iter_difference_t<_It>>((_Hole - 1) >> 1); // shift for codegen
|
||||
if (!_STD invoke(_Pred, _STD invoke(_Proj, *(_First + _Idx)), _STD invoke(_Proj, _Val))) {
|
||||
if (!_STD invoke(_Pred, _STD invoke(_Proj1, *(_First + _Idx)), _STD invoke(_Proj2, _Val))) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -6172,7 +6173,7 @@ namespace ranges {
|
|||
_Hole = _Idx;
|
||||
}
|
||||
|
||||
*(_First + _Hole) = _STD move(_Val); // drop _Val into final hole
|
||||
*(_First + _Hole) = _STD forward<_Ty>(_Val); // drop _Val into final hole
|
||||
}
|
||||
|
||||
class _Push_heap_fn : private _Not_quite_object {
|
||||
|
@ -6217,7 +6218,8 @@ namespace ranges {
|
|||
|
||||
--_Last;
|
||||
iter_value_t<_It> _Val = _RANGES iter_move(_Last);
|
||||
_RANGES _Push_heap_by_index(_STD move(_First), _Count - 1, 0, _STD move(_Val), _Pred, _Proj);
|
||||
// NB: if _Proj is a _Ref_fn, this aliases the _Proj1 and _Proj2 parameters of _Push_heap_by_index
|
||||
_RANGES _Push_heap_by_index(_STD move(_First), _Count - 1, 0, _STD move(_Val), _Pred, _Proj, _Proj);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -6253,7 +6255,7 @@ _CONSTEXPR20 void _Pop_heap_hole_by_index(
|
|||
_Hole = _Bottom - 1;
|
||||
}
|
||||
|
||||
_Push_heap_by_index(_First, _Hole, _Top, _STD move(_Val), _Pred);
|
||||
_Push_heap_by_index(_First, _Hole, _Top, _STD forward<_Ty>(_Val), _Pred);
|
||||
}
|
||||
|
||||
template <class _RanIt, class _Ty, class _Pr>
|
||||
|
@ -6263,7 +6265,8 @@ _CONSTEXPR20 void _Pop_heap_hole_unchecked(_RanIt _First, _RanIt _Last, _RanIt _
|
|||
// precondition: _First != _Dest
|
||||
*_Dest = _STD move(*_First);
|
||||
using _Diff = _Iter_diff_t<_RanIt>;
|
||||
_Pop_heap_hole_by_index(_First, static_cast<_Diff>(0), static_cast<_Diff>(_Last - _First), _STD move(_Val), _Pred);
|
||||
_Pop_heap_hole_by_index(
|
||||
_First, static_cast<_Diff>(0), static_cast<_Diff>(_Last - _First), _STD forward<_Ty>(_Val), _Pred);
|
||||
}
|
||||
|
||||
template <class _RanIt, class _Pr>
|
||||
|
@ -6292,12 +6295,14 @@ _CONSTEXPR20 void pop_heap(_RanIt _First, _RanIt _Last) {
|
|||
#ifdef __cpp_lib_concepts
|
||||
namespace ranges {
|
||||
// VARIABLE ranges::pop_heap
|
||||
template <class _It, class _Pr, class _Pj>
|
||||
// clang-format off
|
||||
template <random_access_iterator _It, class _Ty, class _Pr, class _Pj1, class _Pj2>
|
||||
requires sortable<_It, _Pr, _Pj1> && indirectly_writable<_It, _Ty>
|
||||
&& indirect_strict_weak_order<_Pr, projected<_It, _Pj1>, projected<remove_reference_t<_Ty>*, _Pj2>>
|
||||
constexpr void _Pop_heap_hole_by_index(_It _First, iter_difference_t<_It> _Hole,
|
||||
const iter_difference_t<_It> _Bottom, iter_value_t<_It>&& _Val, _Pr _Pred, _Pj _Proj) {
|
||||
const iter_difference_t<_It> _Bottom, _Ty&& _Val, _Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) {
|
||||
// clang-format on
|
||||
// percolate _Hole to _Bottom, then push _Val
|
||||
_STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>);
|
||||
_STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>);
|
||||
_STL_INTERNAL_CHECK(_Hole >= 0);
|
||||
_STL_INTERNAL_CHECK(_Bottom > 0);
|
||||
|
||||
|
@ -6311,7 +6316,7 @@ namespace ranges {
|
|||
while (_Idx < _Max_sequence_non_leaf) { // move _Hole down to larger child
|
||||
_Idx = 2 * _Idx + 2;
|
||||
auto _Mid = _First + _Idx;
|
||||
if (_STD invoke(_Pred, _STD invoke(_Proj, *_Mid), _STD invoke(_Proj, *_RANGES prev(_Mid)))) {
|
||||
if (_STD invoke(_Pred, _STD invoke(_Proj1, *_Mid), _STD invoke(_Proj1, *_RANGES prev(_Mid)))) {
|
||||
--_Idx;
|
||||
--_Mid;
|
||||
}
|
||||
|
@ -6324,36 +6329,39 @@ namespace ranges {
|
|||
_Hole = _Bottom - 1;
|
||||
}
|
||||
|
||||
_RANGES _Push_heap_by_index(_STD move(_First), _Hole, _Top, _STD move(_Val), _Pred, _Proj);
|
||||
_RANGES _Push_heap_by_index(_STD move(_First), _Hole, _Top, _STD forward<_Ty>(_Val), _Pred, _Proj1, _Proj2);
|
||||
}
|
||||
|
||||
template <class _It, class _Pr, class _Pj>
|
||||
// clang-format off
|
||||
template <random_access_iterator _It, class _Ty, class _Pr, class _Pj1, class _Pj2>
|
||||
requires sortable<_It, _Pr, _Pj1> && indirectly_writable<_It, _Ty>
|
||||
&& indirect_strict_weak_order<_Pr, projected<_It, _Pj1>, projected<remove_reference_t<_Ty>*, _Pj2>>
|
||||
constexpr void _Pop_heap_hole_unchecked(
|
||||
_It _First, const _It _Last, const _It _Dest, iter_value_t<_It>&& _Val, _Pr _Pred, _Pj _Proj) {
|
||||
_It _First, const _It _Last, const _It _Dest, _Ty&& _Val, _Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) {
|
||||
// clang-format on
|
||||
// pop *_First to *_Dest and reheap
|
||||
_STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>);
|
||||
_STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>);
|
||||
_STL_INTERNAL_CHECK(_First != _Last);
|
||||
_STL_INTERNAL_CHECK(_First != _Dest);
|
||||
|
||||
*_Dest = _RANGES iter_move(_First);
|
||||
const auto _Count = _Last - _First;
|
||||
_RANGES _Pop_heap_hole_by_index(_STD move(_First), 0, _Count, _STD move(_Val), _Pred, _Proj);
|
||||
_RANGES _Pop_heap_hole_by_index(_STD move(_First), 0, _Count, _STD forward<_Ty>(_Val), _Pred, _Proj1, _Proj2);
|
||||
}
|
||||
|
||||
template <class _It, class _Pr, class _Pj>
|
||||
// clang-format off
|
||||
template <random_access_iterator _It, class _Pr, class _Pj>
|
||||
requires sortable<_It, _Pr, _Pj>
|
||||
constexpr void _Pop_heap_unchecked(_It _First, _It _Last, _Pr _Pred, _Pj _Proj) {
|
||||
// clang-format on
|
||||
// pop *_First to *(_Last - 1) and reheap
|
||||
_STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>);
|
||||
_STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>);
|
||||
|
||||
if (_Last - _First < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
--_Last;
|
||||
iter_value_t<_It> _Val = _RANGES iter_move(_Last);
|
||||
_RANGES _Pop_heap_hole_unchecked(_STD move(_First), _Last, _Last, _STD move(_Val), _Pred, _Proj);
|
||||
// NB: if _Proj is a _Ref_fn, this aliases the _Proj1 and _Proj2 parameters of _Pop_heap_hole_unchecked
|
||||
_RANGES _Pop_heap_hole_unchecked(_STD move(_First), _Last, _Last, _STD move(_Val), _Pred, _Proj, _Proj);
|
||||
}
|
||||
|
||||
class _Pop_heap_fn : private _Not_quite_object {
|
||||
|
@ -6419,6 +6427,23 @@ _CONSTEXPR20 void make_heap(_RanIt _First, _RanIt _Last) { // make [_First, _Las
|
|||
#ifdef __cpp_lib_concepts
|
||||
namespace ranges {
|
||||
// VARIABLE ranges::make_heap
|
||||
// clang-format off
|
||||
template <random_access_iterator _It, class _Pr, class _Pj>
|
||||
requires sortable<_It, _Pr, _Pj>
|
||||
constexpr void _Make_heap_common(_It _First, _It _Last, _Pr _Pred, _Pj _Proj) {
|
||||
// make nontrivial [_First, _Last) into a heap with respect to _Pred and _Proj
|
||||
// clang-format on
|
||||
using _Diff = iter_difference_t<_It>;
|
||||
const _Diff _Bottom = _Last - _First;
|
||||
for (_Diff _Hole = _Bottom >> 1; _Hole > 0;) { // shift for codegen
|
||||
// reheap top half, bottom to top
|
||||
--_Hole;
|
||||
iter_value_t<_It> _Val = _RANGES iter_move(_First + _Hole);
|
||||
// NB: if _Proj is a _Ref_fn, this aliases the _Proj1 and _Proj2 parameters of _Pop_heap_hole_by_index
|
||||
_RANGES _Pop_heap_hole_by_index(_First, _Hole, _Bottom, _STD move(_Val), _Pred, _Proj, _Proj);
|
||||
}
|
||||
}
|
||||
|
||||
class _Make_heap_fn : private _Not_quite_object {
|
||||
public:
|
||||
using _Not_quite_object::_Not_quite_object;
|
||||
|
@ -6431,7 +6456,7 @@ namespace ranges {
|
|||
auto _UFirst = _Get_unwrapped(_STD move(_First));
|
||||
auto _ULast = _Get_final_iterator_unwrapped<_It>(_UFirst, _STD move(_Last));
|
||||
_Seek_wrapped(_First, _ULast);
|
||||
_Make_heap_unchecked(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
_Make_heap_common(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
return _First;
|
||||
}
|
||||
|
||||
|
@ -6439,31 +6464,15 @@ namespace ranges {
|
|||
requires sortable<iterator_t<_Rng>, _Pr, _Pj>
|
||||
constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const {
|
||||
if constexpr (common_range<_Rng>) {
|
||||
_Make_heap_unchecked(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
_Make_heap_common(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
return _RANGES end(_Range);
|
||||
} else {
|
||||
auto _ULast = _Get_final_iterator_unwrapped(_Range);
|
||||
_Make_heap_unchecked(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
_Make_heap_common(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
return _Rewrap_iterator(_Range, _STD move(_ULast));
|
||||
}
|
||||
}
|
||||
// clang-format on
|
||||
private:
|
||||
template <class _It, class _Pr, class _Pj>
|
||||
static constexpr void _Make_heap_unchecked(_It _First, _It _Last, _Pr _Pred, _Pj _Proj) {
|
||||
// make nontrivial [_First, _Last) into a heap
|
||||
_STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>);
|
||||
_STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>);
|
||||
|
||||
using _Diff = iter_difference_t<_It>;
|
||||
const _Diff _Bottom = _Last - _First;
|
||||
for (_Diff _Hole = _Bottom >> 1; _Hole > 0;) { // shift for codegen
|
||||
// reheap top half, bottom to top
|
||||
--_Hole;
|
||||
iter_value_t<_It> _Val = _RANGES iter_move(_First + _Hole);
|
||||
_RANGES _Pop_heap_hole_by_index(_First, _Hole, _Bottom, _STD move(_Val), _Pred, _Proj);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr _Make_heap_fn make_heap{_Not_quite_object::_Construct_tag{}};
|
||||
|
@ -6652,6 +6661,17 @@ _CONSTEXPR20 void sort_heap(_RanIt _First, _RanIt _Last) { // order heap by repe
|
|||
#ifdef __cpp_lib_concepts
|
||||
namespace ranges {
|
||||
// VARIABLE ranges::sort_heap
|
||||
// clang-format off
|
||||
template <random_access_iterator _It, class _Pr, class _Pj>
|
||||
requires sortable<_It, _Pr, _Pj>
|
||||
constexpr void _Sort_heap_common(const _It _First, _It _Last, _Pr _Pred, _Pj _Proj) {
|
||||
// order heap by repeatedly popping
|
||||
// clang-format on
|
||||
for (; _Last - _First >= 2; --_Last) {
|
||||
_RANGES _Pop_heap_unchecked(_First, _Last, _Pred, _Proj);
|
||||
}
|
||||
}
|
||||
|
||||
class _Sort_heap_fn : private _Not_quite_object {
|
||||
public:
|
||||
using _Not_quite_object::_Not_quite_object;
|
||||
|
@ -6664,7 +6684,7 @@ namespace ranges {
|
|||
auto _UFirst = _Get_unwrapped(_STD move(_First));
|
||||
auto _ULast = _Get_final_iterator_unwrapped<_It>(_UFirst, _STD move(_Last));
|
||||
_Seek_wrapped(_First, _ULast);
|
||||
_Sort_heap_unchecked(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
_Sort_heap_common(_STD move(_UFirst), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
return _First;
|
||||
}
|
||||
|
||||
|
@ -6672,26 +6692,15 @@ namespace ranges {
|
|||
requires sortable<iterator_t<_Rng>, _Pr, _Pj>
|
||||
constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const {
|
||||
if constexpr (common_range<_Rng>) {
|
||||
_Sort_heap_unchecked(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
_Sort_heap_common(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
return _RANGES end(_Range);
|
||||
} else {
|
||||
auto _ULast = _Get_final_iterator_unwrapped(_Range);
|
||||
_Sort_heap_unchecked(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
_Sort_heap_common(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj));
|
||||
return _Rewrap_iterator(_Range, _STD move(_ULast));
|
||||
}
|
||||
}
|
||||
// clang-format on
|
||||
private:
|
||||
template <class _It, class _Pr, class _Pj>
|
||||
static constexpr void _Sort_heap_unchecked(const _It _First, _It _Last, _Pr _Pred, _Pj _Proj) {
|
||||
// order heap by repeatedly popping
|
||||
_STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>);
|
||||
_STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>);
|
||||
|
||||
for (; _Last - _First >= 2; --_Last) {
|
||||
_RANGES _Pop_heap_unchecked(_First, _Last, _Pred, _Proj);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr _Sort_heap_fn sort_heap{_Not_quite_object::_Construct_tag{}};
|
||||
|
@ -8033,8 +8042,8 @@ _CONSTEXPR20 _RanIt partial_sort_copy(_InIt _First1, _InIt _Last1, _RanIt _First
|
|||
if (_DEBUG_LT_PRED(_Pred, *_UFirst1, *_UFirst2)) {
|
||||
// replace top with new largest:
|
||||
using _Diff = _Iter_diff_t<_RanIt>;
|
||||
_Pop_heap_hole_by_index(_UFirst2, static_cast<_Diff>(0), static_cast<_Diff>(_UMid2 - _UFirst2),
|
||||
static_cast<_Iter_value_t<_InIt>>(*_UFirst1), _Pass_fn(_Pred));
|
||||
_Pop_heap_hole_by_index(
|
||||
_UFirst2, static_cast<_Diff>(0), static_cast<_Diff>(_UMid2 - _UFirst2), *_UFirst1, _Pass_fn(_Pred));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -164,6 +164,7 @@ tests\GH_000890_pow_template
|
|||
tests\GH_000940_missing_valarray_copy
|
||||
tests\GH_001010_filesystem_error_encoding
|
||||
tests\GH_001017_discrete_distribution_out_of_range
|
||||
tests\GH_001086_partial_sort_copy
|
||||
tests\LWG2597_complex_branch_cut
|
||||
tests\LWG3018_shared_ptr_function
|
||||
tests\P0024R2_parallel_algorithms_adjacent_difference
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\usual_matrix.lst
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// GH-1086: "std::partial_sort_copy performs an unconstrained operation"
|
||||
// partial_sort_copy was constructing an object of the source range's value type
|
||||
// from the result of dereferencing an iterator, which is not allowed by the
|
||||
// specification of the algorithm.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct wrapper {
|
||||
wrapper() = default;
|
||||
constexpr explicit wrapper(int i) : x{i} {}
|
||||
|
||||
bool operator<(const wrapper& that) const {
|
||||
return x < that.x;
|
||||
}
|
||||
|
||||
int x;
|
||||
};
|
||||
|
||||
struct source : wrapper {
|
||||
source() = default;
|
||||
|
||||
using wrapper::wrapper;
|
||||
|
||||
source(const source&) = delete;
|
||||
source& operator=(const source&) = delete;
|
||||
};
|
||||
|
||||
struct target : wrapper {
|
||||
target() = default;
|
||||
|
||||
using wrapper::wrapper;
|
||||
|
||||
target(target&&) = default;
|
||||
target& operator=(target&&) = default;
|
||||
|
||||
target& operator=(const source& w) {
|
||||
x = w.x;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
constexpr int src_size = 4;
|
||||
source src[src_size];
|
||||
constexpr int dst_size = 2;
|
||||
target dst[dst_size];
|
||||
|
||||
for (int i = 0; i < src_size; ++i) {
|
||||
src[i].x = src_size - 1 - i;
|
||||
}
|
||||
|
||||
partial_sort_copy(begin(src), end(src), begin(dst), end(dst));
|
||||
|
||||
for (int i = 0; i < dst_size; ++i) {
|
||||
assert(dst[i].x == i);
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче