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
457 changes: 434 additions & 23 deletions stl/inc/algorithm

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions stl/inc/array
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,7 @@ private:
}

if (_Off < 0) {
#pragma warning(suppress : 4146) // unary minus operator applied to unsigned type, result still unsigned
_STL_VERIFY(_Idx >= -static_cast<size_t>(_Off), "cannot seek array iterator before begin");
_STL_VERIFY(_Idx >= size_t{0} - static_cast<size_t>(_Off), "cannot seek array iterator before begin");
}

if (_Off > 0) {
Expand All @@ -204,7 +203,7 @@ private:

_CONSTEXPR17 _Array_const_iterator& operator+=(const ptrdiff_t _Off) noexcept {
_Verify_offset(_Off);
_Idx += _Off;
_Idx += static_cast<size_t>(_Off);
return *this;
}

Expand Down
14 changes: 6 additions & 8 deletions stl/inc/iterator
Original file line number Diff line number Diff line change
Expand Up @@ -582,8 +582,8 @@ public:
}

if (_Off < 0) {
#pragma warning(suppress : 4146) // unary minus operator applied to unsigned type, result still unsigned
_STL_VERIFY(_Myindex >= -static_cast<size_t>(_Off), "cannot seek checked_array_iterator before begin");
_STL_VERIFY(
_Myindex >= size_t{0} - static_cast<size_t>(_Off), "cannot seek checked_array_iterator before begin");
}

if (_Off > 0) {
Expand Down Expand Up @@ -619,9 +619,8 @@ public:
}

if (_Off < 0) {
#pragma warning(suppress : 4146) // unary minus operator applied to unsigned type, result still unsigned
_STL_VERIFY(
_Mysize - _Myindex >= -static_cast<size_t>(_Off), "cannot seek checked_array_iterator after end");
_STL_VERIFY(_Mysize - _Myindex >= size_t{0} - static_cast<size_t>(_Off),
"cannot seek checked_array_iterator after end");
}

_Myindex -= _Off;
Expand Down Expand Up @@ -681,9 +680,8 @@ public:

constexpr void _Verify_offset(const difference_type _Off) const noexcept {
if (_Off < 0) {
#pragma warning(suppress : 4146) // unary minus operator applied to unsigned type, result still unsigned
_STL_VERIFY(
_Myindex >= -static_cast<size_t>(_Off), "cannot seek checked_array_iterator iterator before begin");
_STL_VERIFY(_Myindex >= size_t{0} - static_cast<size_t>(_Off),
"cannot seek checked_array_iterator iterator before begin");
}

if (_Off > 0) {
Expand Down
9 changes: 4 additions & 5 deletions stl/inc/xstring
Original file line number Diff line number Diff line change
Expand Up @@ -1033,8 +1033,8 @@ public:
}

if (_Off < 0) {
#pragma warning(suppress : 4146) // unary minus operator applied to unsigned type, result still unsigned
_STL_VERIFY(_Myoff >= -static_cast<size_t>(_Off), "cannot seek string_view iterator before begin");
_STL_VERIFY(
_Myoff >= size_t{0} - static_cast<size_t>(_Off), "cannot seek string_view iterator before begin");
}

if (_Off > 0) {
Expand Down Expand Up @@ -1073,8 +1073,8 @@ public:
}

if (_Off < 0) {
#pragma warning(suppress : 4146) // unary minus operator applied to unsigned type, result still unsigned
_STL_VERIFY(_Mysize - _Myoff >= -static_cast<size_t>(_Off), "cannot seek string_view iterator after end");
_STL_VERIFY(_Mysize - _Myoff >= size_t{0} - static_cast<size_t>(_Off),
"cannot seek string_view iterator after end");
}

_Myoff -= _Off;
Expand Down Expand Up @@ -1903,7 +1903,6 @@ public:
const auto _Rawptr = _Unfancy(_Ptr);

if (_Off < 0) {
#pragma warning(suppress : 4146) // unary minus operator applied to unsigned type, result still unsigned
_STL_VERIFY(_Contptr - _Rawptr <= _Off, "cannot seek string iterator before begin");
}

Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ tests\P0896R4_ranges_alg_find_if
tests\P0896R4_ranges_alg_find_if_not
tests\P0896R4_ranges_alg_for_each
tests\P0896R4_ranges_alg_for_each_n
tests\P0896R4_ranges_alg_heap
tests\P0896R4_ranges_alg_is_permutation
tests\P0896R4_ranges_alg_is_sorted
tests\P0896R4_ranges_alg_minmax
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0896R4_ranges_alg_heap/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 ..\concepts_matrix.lst
219 changes: 219 additions & 0 deletions tests/std/tests/P0896R4_ranges_alg_heap/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// Covers ranges::push_heap, ranges::pop_heap, ranges::make_heap, ranges::is_heap, ranges::is_heap_until, and
// ranges::sort_heap

#include <algorithm>
#include <array>
#include <cassert>
#include <concepts>
#include <ranges>
#include <utility>

#include <range_algorithm_support.hpp>

using namespace std;

#define ASSERT(...) assert((__VA_ARGS__))

// Validate dangling story
STATIC_ASSERT(same_as<decltype(ranges::push_heap(borrowed<false>{})), ranges::dangling>);
STATIC_ASSERT(same_as<decltype(ranges::push_heap(borrowed<true>{})), int*>);
STATIC_ASSERT(same_as<decltype(ranges::pop_heap(borrowed<false>{})), ranges::dangling>);
STATIC_ASSERT(same_as<decltype(ranges::pop_heap(borrowed<true>{})), int*>);
STATIC_ASSERT(same_as<decltype(ranges::make_heap(borrowed<false>{})), ranges::dangling>);
STATIC_ASSERT(same_as<decltype(ranges::make_heap(borrowed<true>{})), int*>);
STATIC_ASSERT(same_as<decltype(ranges::sort_heap(borrowed<false>{})), ranges::dangling>);
STATIC_ASSERT(same_as<decltype(ranges::sort_heap(borrowed<true>{})), int*>);
STATIC_ASSERT(same_as<decltype(ranges::is_heap_until(borrowed<false>{})), ranges::dangling>);
STATIC_ASSERT(same_as<decltype(ranges::is_heap_until(borrowed<true>{})), int*>);

using P = pair<int, int>;

struct empty_ranges {
template <ranges::random_access_range Range>
static constexpr void call() {
// Validate empty ranges (only make_heap and sort_heap accept empty ranges)
const Range range{};

ASSERT(ranges::make_heap(range, ranges::less{}, get_first) == ranges::end(range));
ASSERT(ranges::make_heap(ranges::begin(range), ranges::end(range), ranges::less{}, get_first)
== ranges::end(range));

ASSERT(ranges::sort_heap(range, ranges::less{}, get_first) == ranges::end(range));
ASSERT(ranges::sort_heap(ranges::begin(range), ranges::end(range), ranges::less{}, get_first)
== ranges::end(range));
}
};

struct is_heap_test {
template <ranges::random_access_range Range>
static constexpr void call() {
// Validate is_heap and is_heap_until
using ranges::is_heap, ranges::is_heap_until, ranges::less, ranges::swap;

array buff = {
P{1668617627, 0},
P{1429106719, 1},
P{-47163201, 2},
P{-441494788, 3},
P{-1200257975, 4},
P{-1459960308, 5},
P{-912489821, 6},
P{-2095681771, 7},
P{-1298559576, 8},
P{-1260655766, 9},
};
const Range wrapped{buff};

ASSERT(is_heap(wrapped, less{}, get_first));
ASSERT(is_heap(wrapped.begin(), wrapped.end(), less{}, get_first));

ASSERT(is_heap_until(wrapped, less{}, get_first) == wrapped.end());
ASSERT(is_heap_until(wrapped.begin(), wrapped.end(), less{}, get_first) == wrapped.end());

swap(buff[0], buff[1]);

ASSERT(!is_heap(wrapped, less{}, get_first));
ASSERT(!is_heap(wrapped.begin(), wrapped.end(), less{}, get_first));

ASSERT(is_heap_until(wrapped, less{}, get_first) == wrapped.begin() + 1);
ASSERT(is_heap_until(wrapped.begin(), wrapped.end(), less{}, get_first) == wrapped.begin() + 1);
}
};

struct make_and_sort_heap_test {
static constexpr array initial_values = {
P{-1200257975, 0},
P{-1260655766, 1},
P{-1298559576, 2},
P{-1459960308, 3},
P{-2095681771, 4},
P{-441494788, 5},
P{-47163201, 6},
P{-912489821, 7},
P{1429106719, 8},
P{1668617627, 9},
};

template <ranges::random_access_range Range>
static constexpr void call() {
// Validate make_heap and sort_heap
using ranges::make_heap, ranges::sort_heap, ranges::is_heap, ranges::is_sorted, ranges::less, ranges::swap;

{
auto buff = initial_values;
const Range wrapped{buff};

ASSERT(!is_heap(wrapped, less{}, get_first));

make_heap(wrapped, less{}, get_first);
ASSERT(is_heap(wrapped, less{}, get_first));

sort_heap(wrapped, less{}, get_first);
ASSERT(is_sorted(wrapped, less{}, get_first));
}

{
auto buff = initial_values;
const Range wrapped{buff};

ASSERT(!is_heap(wrapped.begin(), wrapped.end(), less{}, get_first));

make_heap(wrapped.begin(), wrapped.end(), less{}, get_first);
ASSERT(is_heap(wrapped.begin(), wrapped.end(), less{}, get_first));

sort_heap(wrapped.begin(), wrapped.end(), less{}, get_first);
ASSERT(is_sorted(wrapped.begin(), wrapped.end(), less{}, get_first));
}
}
};

struct push_and_pop_heap_test {
static constexpr array initial_values = {
P{1668617627, 0},
P{1429106719, 1},
P{-47163201, 2},
P{-441494788, 3},
P{-1200257975, 4},
P{-1459960308, 5},
P{-912489821, 6},
P{-2095681771, 7},
P{-1298559576, 8},
P{-1260655766, 9},
};
STATIC_ASSERT(ranges::is_heap(initial_values, ranges::less{}, get_first));

static constexpr array expectedPushed = {
P{1668617627, 0},
P{1429106719, 1},
P{-47163201, 2},
P{-1260655766, 9},
P{-441494788, 3},
P{-1459960308, 5},
P{-912489821, 6},
P{-2095681771, 7},
P{-1298559576, 8},
P{-1200257975, 4},
};
STATIC_ASSERT(ranges::is_heap(expectedPushed, ranges::less{}, get_first));

static constexpr array expectedPopped = {
P{1429106719, 1},
P{-441494788, 3},
P{-47163201, 2},
P{-1260655766, 9},
P{-1200257975, 4},
P{-1459960308, 5},
P{-912489821, 6},
P{-2095681771, 7},
P{-1298559576, 8},
P{1668617627, 0},
};
STATIC_ASSERT(ranges::is_heap(expectedPopped.begin(), expectedPopped.end() - 1, ranges::less{}, get_first));

template <ranges::random_access_range Range>
static constexpr void call() {
// Validate push_heap and pop_heap
using ranges::push_heap, ranges::pop_heap, ranges::equal, ranges::is_heap, ranges::less;

{
auto buff = initial_values;
const Range wrapped{buff};

pop_heap(wrapped, less{}, get_first);
ASSERT(equal(wrapped, expectedPopped));

push_heap(wrapped, less{}, get_first);
ASSERT(equal(wrapped, expectedPushed));
}

{
auto buff = initial_values;
const Range wrapped{buff};

pop_heap(wrapped.begin(), wrapped.end(), less{}, get_first);
ASSERT(is_heap(expectedPopped.begin(), expectedPopped.end() - 1, less{}, get_first));
ASSERT(equal(wrapped.begin(), wrapped.end(), expectedPopped.begin(), expectedPopped.end()));

push_heap(wrapped.begin(), wrapped.end(), less{}, get_first);
ASSERT(is_heap(expectedPushed, less{}, get_first));
ASSERT(equal(wrapped.begin(), wrapped.end(), expectedPushed.begin(), expectedPushed.end()));
}
}
};

int main() {
STATIC_ASSERT((test_random<empty_ranges, P>(), true));
test_random<empty_ranges, P>();

STATIC_ASSERT((test_random<is_heap_test, P>(), true));
test_random<is_heap_test, P>();

STATIC_ASSERT((test_random<make_and_sort_heap_test, P>(), true));
test_random<make_and_sort_heap_test, P>();

STATIC_ASSERT((test_random<push_and_pop_heap_test, P>(), true));
test_random<push_and_pop_heap_test, P>();
}