|
|
diff -up chromium-86.0.4240.111/base/callback_list.h.a61fb57e chromium-86.0.4240.111/base/callback_list.h
|
|
|
--- chromium-86.0.4240.111/base/callback_list.h.a61fb57e 2020-10-20 20:14:17.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/callback_list.h 2020-10-21 17:11:20.000228716 -0400
|
|
|
@@ -5,7 +5,6 @@
|
|
|
#ifndef BASE_CALLBACK_LIST_H_
|
|
|
#define BASE_CALLBACK_LIST_H_
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <list>
|
|
|
#include <memory>
|
|
|
#include <utility>
|
|
|
@@ -17,6 +16,7 @@
|
|
|
#include "base/check.h"
|
|
|
#include "base/compiler_specific.h"
|
|
|
#include "base/memory/weak_ptr.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
|
|
|
// OVERVIEW:
|
|
|
@@ -163,8 +163,8 @@ class CallbackListBase {
|
|
|
// Returns whether the list of registered callbacks is empty (from an external
|
|
|
// perspective -- meaning no remaining callbacks are live).
|
|
|
bool empty() const {
|
|
|
- return std::all_of(callbacks_.cbegin(), callbacks_.cend(),
|
|
|
- [](const auto& callback) { return callback.is_null(); });
|
|
|
+ return ranges::all_of(
|
|
|
+ callbacks_, [](const auto& callback) { return callback.is_null(); });
|
|
|
}
|
|
|
|
|
|
// Calls all registered callbacks that are not canceled beforehand. If any
|
|
|
diff -up chromium-86.0.4240.111/base/command_line.cc.a61fb57e chromium-86.0.4240.111/base/command_line.cc
|
|
|
--- chromium-86.0.4240.111/base/command_line.cc.a61fb57e 2020-10-20 20:14:17.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/command_line.cc 2020-10-21 17:11:20.000228716 -0400
|
|
|
@@ -4,13 +4,13 @@
|
|
|
|
|
|
#include "base/command_line.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <ostream>
|
|
|
|
|
|
#include "base/containers/span.h"
|
|
|
#include "base/files/file_path.h"
|
|
|
#include "base/logging.h"
|
|
|
#include "base/notreached.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/strings/strcat.h"
|
|
|
#include "base/strings/string_split.h"
|
|
|
@@ -411,8 +411,7 @@ CommandLine::StringVector CommandLine::G
|
|
|
// Gather all arguments after the last switch (may include kSwitchTerminator).
|
|
|
StringVector args(argv_.begin() + begin_args_, argv_.end());
|
|
|
// Erase only the first kSwitchTerminator (maybe "--" is a legitimate page?)
|
|
|
- auto switch_terminator =
|
|
|
- std::find(args.begin(), args.end(), kSwitchTerminator);
|
|
|
+ auto switch_terminator = ranges::find(args, kSwitchTerminator);
|
|
|
if (switch_terminator != args.end())
|
|
|
args.erase(switch_terminator);
|
|
|
return args;
|
|
|
diff -up chromium-86.0.4240.111/base/containers/checked_range_unittest.cc.a61fb57e chromium-86.0.4240.111/base/containers/checked_range_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/containers/checked_range_unittest.cc.a61fb57e 2020-10-20 20:14:17.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/containers/checked_range_unittest.cc 2020-10-21 17:11:20.001228724 -0400
|
|
|
@@ -8,6 +8,7 @@
|
|
|
#include <initializer_list>
|
|
|
#include <type_traits>
|
|
|
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/strings/string_piece.h"
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
|
|
@@ -151,9 +152,9 @@ TEST(CheckedContiguousRange, Mutable_Dat
|
|
|
std::vector<int> vector = {3, 1, 4, 2, 5};
|
|
|
CheckedContiguousRange<std::vector<int>> range(vector);
|
|
|
|
|
|
- EXPECT_FALSE(std::is_sorted(vector.begin(), vector.end()));
|
|
|
+ EXPECT_FALSE(ranges::is_sorted(vector));
|
|
|
std::sort(range.data(), range.data() + range.size());
|
|
|
- EXPECT_TRUE(std::is_sorted(vector.begin(), vector.end()));
|
|
|
+ EXPECT_TRUE(ranges::is_sorted(vector));
|
|
|
}
|
|
|
|
|
|
TEST(CheckedContiguousRange, DataSizeEmpty_Constexpr) {
|
|
|
diff -up chromium-86.0.4240.111/base/containers/circular_deque.h.a61fb57e chromium-86.0.4240.111/base/containers/circular_deque.h
|
|
|
--- chromium-86.0.4240.111/base/containers/circular_deque.h.a61fb57e 2020-10-20 20:14:17.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/containers/circular_deque.h 2020-10-21 17:11:20.001228724 -0400
|
|
|
@@ -14,6 +14,7 @@
|
|
|
#include "base/check_op.h"
|
|
|
#include "base/containers/vector_buffer.h"
|
|
|
#include "base/macros.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/template_util.h"
|
|
|
|
|
|
@@ -1097,7 +1098,7 @@ class circular_deque {
|
|
|
// Implementations of base::Erase[If] (see base/stl_util.h).
|
|
|
template <class T, class Value>
|
|
|
size_t Erase(circular_deque<T>& container, const Value& value) {
|
|
|
- auto it = std::remove(container.begin(), container.end(), value);
|
|
|
+ auto it = ranges::remove(container, value);
|
|
|
size_t removed = std::distance(it, container.end());
|
|
|
container.erase(it, container.end());
|
|
|
return removed;
|
|
|
@@ -1105,7 +1106,7 @@ size_t Erase(circular_deque<T>& containe
|
|
|
|
|
|
template <class T, class Predicate>
|
|
|
size_t EraseIf(circular_deque<T>& container, Predicate pred) {
|
|
|
- auto it = std::remove_if(container.begin(), container.end(), pred);
|
|
|
+ auto it = ranges::remove_if(container, pred);
|
|
|
size_t removed = std::distance(it, container.end());
|
|
|
container.erase(it, container.end());
|
|
|
return removed;
|
|
|
diff -up chromium-86.0.4240.111/base/containers/flat_map_unittest.cc.a61fb57e chromium-86.0.4240.111/base/containers/flat_map_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/containers/flat_map_unittest.cc.a61fb57e 2020-10-20 20:14:17.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/containers/flat_map_unittest.cc 2020-10-21 17:11:20.001228724 -0400
|
|
|
@@ -8,6 +8,7 @@
|
|
|
#include <vector>
|
|
|
|
|
|
#include "base/macros.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/strings/string_piece.h"
|
|
|
#include "base/test/move_only_int.h"
|
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
|
@@ -214,7 +215,7 @@ TEST(FlatMap, InsertOrAssignMoveOnlyKey)
|
|
|
base::flat_map<MoveOnlyInt, int> map;
|
|
|
for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
|
|
|
map.insert_or_assign(MoveOnlyInt(i), i);
|
|
|
- EXPECT_TRUE(std::is_sorted(map.begin(), map.end()));
|
|
|
+ EXPECT_TRUE(ranges::is_sorted(map));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -249,7 +250,7 @@ TEST(FlatMap, InsertOrAssignMoveOnlyKeyW
|
|
|
base::flat_map<MoveOnlyInt, int> map;
|
|
|
for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
|
|
|
map.insert_or_assign(map.end(), MoveOnlyInt(i), i);
|
|
|
- EXPECT_TRUE(std::is_sorted(map.begin(), map.end()));
|
|
|
+ EXPECT_TRUE(ranges::is_sorted(map));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -294,7 +295,7 @@ TEST(FlatMap, TryEmplaceMoveOnlyKey) {
|
|
|
base::flat_map<MoveOnlyInt, int> map;
|
|
|
for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
|
|
|
map.try_emplace(MoveOnlyInt(i), i);
|
|
|
- EXPECT_TRUE(std::is_sorted(map.begin(), map.end()));
|
|
|
+ EXPECT_TRUE(ranges::is_sorted(map));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -340,7 +341,7 @@ TEST(FlatMap, TryEmplaceMoveOnlyKeyWithH
|
|
|
base::flat_map<MoveOnlyInt, int> map;
|
|
|
for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
|
|
|
map.try_emplace(map.end(), MoveOnlyInt(i), i);
|
|
|
- EXPECT_TRUE(std::is_sorted(map.begin(), map.end()));
|
|
|
+ EXPECT_TRUE(ranges::is_sorted(map));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
diff -up chromium-86.0.4240.111/base/containers/flat_tree.h.a61fb57e chromium-86.0.4240.111/base/containers/flat_tree.h
|
|
|
--- chromium-86.0.4240.111/base/containers/flat_tree.h.a61fb57e 2020-10-20 20:14:17.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/containers/flat_tree.h 2020-10-21 17:11:20.002228733 -0400
|
|
|
@@ -11,6 +11,7 @@
|
|
|
#include <utility>
|
|
|
#include <vector>
|
|
|
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/template_util.h"
|
|
|
|
|
|
@@ -753,11 +754,10 @@ template <class Key, class Value, class
|
|
|
void flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::replace(
|
|
|
underlying_type&& body) {
|
|
|
// Ensure that |body| is sorted and has no repeated elements.
|
|
|
- DCHECK(std::is_sorted(body.begin(), body.end(), value_comp()));
|
|
|
- DCHECK(std::adjacent_find(body.begin(), body.end(),
|
|
|
- [this](const auto& lhs, const auto& rhs) {
|
|
|
- return !value_comp()(lhs, rhs);
|
|
|
- }) == body.end());
|
|
|
+ DCHECK(ranges::is_sorted(body, value_comp()));
|
|
|
+ DCHECK(ranges::adjacent_find(body, [this](const auto& lhs, const auto& rhs) {
|
|
|
+ return !value_comp()(lhs, rhs);
|
|
|
+ }) == body.end());
|
|
|
impl_.body_ = std::move(body);
|
|
|
}
|
|
|
|
|
|
@@ -883,7 +883,7 @@ auto flat_tree<Key, Value, GetKeyFromVal
|
|
|
const KeyTypeOrK<K>& key_ref = key;
|
|
|
|
|
|
KeyValueCompare key_value(impl_.get_key_comp());
|
|
|
- return std::lower_bound(begin(), end(), key_ref, key_value);
|
|
|
+ return ranges::lower_bound(*this, key_ref, key_value);
|
|
|
}
|
|
|
|
|
|
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
|
|
|
@@ -904,7 +904,7 @@ auto flat_tree<Key, Value, GetKeyFromVal
|
|
|
const KeyTypeOrK<K>& key_ref = key;
|
|
|
|
|
|
KeyValueCompare key_value(impl_.get_key_comp());
|
|
|
- return std::upper_bound(begin(), end(), key_ref, key_value);
|
|
|
+ return ranges::upper_bound(*this, key_ref, key_value);
|
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
@@ -978,7 +978,7 @@ size_t EraseIf(
|
|
|
base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>&
|
|
|
container,
|
|
|
Predicate pred) {
|
|
|
- auto it = std::remove_if(container.begin(), container.end(), pred);
|
|
|
+ auto it = ranges::remove_if(container, pred);
|
|
|
size_t removed = std::distance(it, container.end());
|
|
|
container.erase(it, container.end());
|
|
|
return removed;
|
|
|
diff -up chromium-86.0.4240.111/base/containers/flat_tree_unittest.cc.a61fb57e chromium-86.0.4240.111/base/containers/flat_tree_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/containers/flat_tree_unittest.cc.a61fb57e 2020-10-20 20:14:17.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/containers/flat_tree_unittest.cc 2020-10-21 17:11:20.003228742 -0400
|
|
|
@@ -35,6 +35,7 @@
|
|
|
#include <string>
|
|
|
#include <vector>
|
|
|
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/template_util.h"
|
|
|
#include "base/test/move_only_int.h"
|
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
|
@@ -218,8 +219,8 @@ TEST(FlatTree, Stability) {
|
|
|
Tree cont({{0, 0}, {1, 0}, {0, 1}, {2, 0}, {0, 2}, {1, 1}});
|
|
|
|
|
|
auto AllOfSecondsAreZero = [&cont] {
|
|
|
- return std::all_of(cont.begin(), cont.end(),
|
|
|
- [](const Pair& elem) { return elem.second == 0; });
|
|
|
+ return ranges::all_of(cont,
|
|
|
+ [](const Pair& elem) { return elem.second == 0; });
|
|
|
};
|
|
|
|
|
|
EXPECT_TRUE(AllOfSecondsAreZero()) << "constructor should be stable";
|
|
|
@@ -975,11 +976,11 @@ TEST(FlatTree, EraseEndDeath) {
|
|
|
TEST(FlatTree, KeyComp) {
|
|
|
ReversedTree cont({1, 2, 3, 4, 5});
|
|
|
|
|
|
- EXPECT_TRUE(std::is_sorted(cont.begin(), cont.end(), cont.key_comp()));
|
|
|
+ EXPECT_TRUE(ranges::is_sorted(cont, cont.key_comp()));
|
|
|
int new_elements[] = {6, 7, 8, 9, 10};
|
|
|
std::copy(std::begin(new_elements), std::end(new_elements),
|
|
|
std::inserter(cont, cont.end()));
|
|
|
- EXPECT_TRUE(std::is_sorted(cont.begin(), cont.end(), cont.key_comp()));
|
|
|
+ EXPECT_TRUE(ranges::is_sorted(cont, cont.key_comp()));
|
|
|
}
|
|
|
|
|
|
// value_compare value_comp() const
|
|
|
@@ -987,11 +988,11 @@ TEST(FlatTree, KeyComp) {
|
|
|
TEST(FlatTree, ValueComp) {
|
|
|
ReversedTree cont({1, 2, 3, 4, 5});
|
|
|
|
|
|
- EXPECT_TRUE(std::is_sorted(cont.begin(), cont.end(), cont.value_comp()));
|
|
|
+ EXPECT_TRUE(ranges::is_sorted(cont, cont.value_comp()));
|
|
|
int new_elements[] = {6, 7, 8, 9, 10};
|
|
|
std::copy(std::begin(new_elements), std::end(new_elements),
|
|
|
std::inserter(cont, cont.end()));
|
|
|
- EXPECT_TRUE(std::is_sorted(cont.begin(), cont.end(), cont.value_comp()));
|
|
|
+ EXPECT_TRUE(ranges::is_sorted(cont, cont.value_comp()));
|
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
diff -up chromium-86.0.4240.111/base/containers/span_unittest.cc.a61fb57e chromium-86.0.4240.111/base/containers/span_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/containers/span_unittest.cc.a61fb57e 2020-10-20 20:14:17.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/containers/span_unittest.cc 2020-10-21 17:11:20.003228742 -0400
|
|
|
@@ -6,7 +6,6 @@
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <iterator>
|
|
|
#include <memory>
|
|
|
#include <string>
|
|
|
@@ -14,6 +13,7 @@
|
|
|
#include <vector>
|
|
|
|
|
|
#include "base/containers/checked_iterators.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/strings/string_piece.h"
|
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
|
@@ -1382,7 +1382,7 @@ TEST(SpanTest, Sort) {
|
|
|
int array[] = {5, 4, 3, 2, 1};
|
|
|
|
|
|
span<int> dynamic_span = array;
|
|
|
- std::sort(dynamic_span.begin(), dynamic_span.end());
|
|
|
+ ranges::sort(dynamic_span);
|
|
|
EXPECT_THAT(array, ElementsAre(1, 2, 3, 4, 5));
|
|
|
std::sort(dynamic_span.rbegin(), dynamic_span.rend());
|
|
|
EXPECT_THAT(array, ElementsAre(5, 4, 3, 2, 1));
|
|
|
@@ -1390,7 +1390,7 @@ TEST(SpanTest, Sort) {
|
|
|
span<int, 5> static_span = array;
|
|
|
std::sort(static_span.rbegin(), static_span.rend(), std::greater<>());
|
|
|
EXPECT_THAT(array, ElementsAre(1, 2, 3, 4, 5));
|
|
|
- std::sort(static_span.begin(), static_span.end(), std::greater<>());
|
|
|
+ ranges::sort(static_span, std::greater<>());
|
|
|
EXPECT_THAT(array, ElementsAre(5, 4, 3, 2, 1));
|
|
|
}
|
|
|
|
|
|
diff -up chromium-86.0.4240.111/base/containers/unique_ptr_adapters_unittest.cc.a61fb57e chromium-86.0.4240.111/base/containers/unique_ptr_adapters_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/containers/unique_ptr_adapters_unittest.cc.a61fb57e 2020-10-20 20:14:17.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/containers/unique_ptr_adapters_unittest.cc 2020-10-21 17:11:20.004228750 -0400
|
|
|
@@ -4,10 +4,10 @@
|
|
|
|
|
|
#include "base/containers/unique_ptr_adapters.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <memory>
|
|
|
#include <vector>
|
|
|
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
|
|
namespace base {
|
|
|
@@ -76,19 +76,19 @@ TEST(UniquePtrMatcherTest, Basic) {
|
|
|
v.push_back(std::move(foo_ptr2));
|
|
|
|
|
|
{
|
|
|
- auto iter = std::find_if(v.begin(), v.end(), UniquePtrMatcher<Foo>(foo1));
|
|
|
+ auto iter = ranges::find_if(v, UniquePtrMatcher<Foo>(foo1));
|
|
|
ASSERT_TRUE(iter != v.end());
|
|
|
EXPECT_EQ(foo1, iter->get());
|
|
|
}
|
|
|
|
|
|
{
|
|
|
- auto iter = std::find_if(v.begin(), v.end(), UniquePtrMatcher<Foo>(foo2));
|
|
|
+ auto iter = ranges::find_if(v, UniquePtrMatcher<Foo>(foo2));
|
|
|
ASSERT_TRUE(iter != v.end());
|
|
|
EXPECT_EQ(foo2, iter->get());
|
|
|
}
|
|
|
|
|
|
{
|
|
|
- auto iter = std::find_if(v.begin(), v.end(), MatchesUniquePtr(foo2));
|
|
|
+ auto iter = ranges::find_if(v, MatchesUniquePtr(foo2));
|
|
|
ASSERT_TRUE(iter != v.end());
|
|
|
EXPECT_EQ(foo2, iter->get());
|
|
|
}
|
|
|
@@ -110,22 +110,19 @@ TEST(UniquePtrMatcherTest, Deleter) {
|
|
|
v.push_back(std::move(foo_ptr2));
|
|
|
|
|
|
{
|
|
|
- auto iter = std::find_if(v.begin(), v.end(),
|
|
|
- UniquePtrMatcher<Foo, TestDeleter>(foo1));
|
|
|
+ auto iter = ranges::find_if(v, UniquePtrMatcher<Foo, TestDeleter>(foo1));
|
|
|
ASSERT_TRUE(iter != v.end());
|
|
|
EXPECT_EQ(foo1, iter->get());
|
|
|
}
|
|
|
|
|
|
{
|
|
|
- auto iter = std::find_if(v.begin(), v.end(),
|
|
|
- UniquePtrMatcher<Foo, TestDeleter>(foo2));
|
|
|
+ auto iter = ranges::find_if(v, UniquePtrMatcher<Foo, TestDeleter>(foo2));
|
|
|
ASSERT_TRUE(iter != v.end());
|
|
|
EXPECT_EQ(foo2, iter->get());
|
|
|
}
|
|
|
|
|
|
{
|
|
|
- auto iter = std::find_if(v.begin(), v.end(),
|
|
|
- MatchesUniquePtr<Foo, TestDeleter>(foo2));
|
|
|
+ auto iter = ranges::find_if(v, MatchesUniquePtr<Foo, TestDeleter>(foo2));
|
|
|
ASSERT_TRUE(iter != v.end());
|
|
|
EXPECT_EQ(foo2, iter->get());
|
|
|
}
|
|
|
diff -up chromium-86.0.4240.111/base/debug/activity_analyzer.cc.a61fb57e chromium-86.0.4240.111/base/debug/activity_analyzer.cc
|
|
|
--- chromium-86.0.4240.111/base/debug/activity_analyzer.cc.a61fb57e 2020-10-20 20:14:17.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/debug/activity_analyzer.cc 2020-10-21 17:11:20.004228750 -0400
|
|
|
@@ -4,7 +4,6 @@
|
|
|
|
|
|
#include "base/debug/activity_analyzer.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <utility>
|
|
|
|
|
|
#include "base/check_op.h"
|
|
|
@@ -14,6 +13,7 @@
|
|
|
#include "base/metrics/histogram_functions.h"
|
|
|
#include "base/metrics/histogram_macros.h"
|
|
|
#include "base/no_destructor.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/strings/string_util.h"
|
|
|
|
|
|
@@ -398,7 +398,7 @@ void GlobalActivityAnalyzer::PrepareAllA
|
|
|
}
|
|
|
|
|
|
// Reverse the list of PIDs so that they get popped in the order found.
|
|
|
- std::reverse(process_ids_.begin(), process_ids_.end());
|
|
|
+ ranges::reverse(process_ids_);
|
|
|
}
|
|
|
|
|
|
} // namespace debug
|
|
|
diff -up chromium-86.0.4240.111/base/debug/task_trace.cc.a61fb57e chromium-86.0.4240.111/base/debug/task_trace.cc
|
|
|
--- chromium-86.0.4240.111/base/debug/task_trace.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/debug/task_trace.cc 2020-10-21 17:11:20.004228750 -0400
|
|
|
@@ -4,13 +4,13 @@
|
|
|
|
|
|
#include "base/debug/task_trace.h"
|
|
|
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "build/build_config.h"
|
|
|
|
|
|
#if defined(OS_ANDROID)
|
|
|
#include <android/log.h>
|
|
|
#endif // OS_ANDROID
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <iostream>
|
|
|
#include <sstream>
|
|
|
|
|
|
@@ -55,8 +55,7 @@ TaskTrace::TaskTrace() {
|
|
|
return;
|
|
|
std::array<const void*, PendingTask::kTaskBacktraceLength + 1> task_trace;
|
|
|
task_trace[0] = current_task->posted_from.program_counter();
|
|
|
- std::copy(current_task->task_backtrace.begin(),
|
|
|
- current_task->task_backtrace.end(), task_trace.begin() + 1);
|
|
|
+ ranges::copy(current_task->task_backtrace, task_trace.begin() + 1);
|
|
|
size_t length = 0;
|
|
|
while (length < task_trace.size() && task_trace[length])
|
|
|
++length;
|
|
|
diff -up chromium-86.0.4240.111/base/feature_list_unittest.cc.a61fb57e chromium-86.0.4240.111/base/feature_list_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/feature_list_unittest.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/feature_list_unittest.cc 2020-10-21 17:11:20.005228759 -0400
|
|
|
@@ -6,7 +6,6 @@
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <utility>
|
|
|
#include <vector>
|
|
|
|
|
|
@@ -14,6 +13,7 @@
|
|
|
#include "base/memory/read_only_shared_memory_region.h"
|
|
|
#include "base/metrics/field_trial.h"
|
|
|
#include "base/metrics/persistent_memory_allocator.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/strings/string_piece.h"
|
|
|
#include "base/strings/string_util.h"
|
|
|
@@ -39,7 +39,7 @@ struct Feature kFeatureOffByDefault {
|
|
|
std::string SortFeatureListString(const std::string& feature_list) {
|
|
|
std::vector<base::StringPiece> features =
|
|
|
FeatureList::SplitFeatureListString(feature_list);
|
|
|
- std::sort(features.begin(), features.end());
|
|
|
+ ranges::sort(features);
|
|
|
return JoinString(features, ",");
|
|
|
}
|
|
|
|
|
|
diff -up chromium-86.0.4240.111/base/hash/sha1_perftest.cc.a61fb57e chromium-86.0.4240.111/base/hash/sha1_perftest.cc
|
|
|
--- chromium-86.0.4240.111/base/hash/sha1_perftest.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/hash/sha1_perftest.cc 2020-10-21 17:11:20.005228759 -0400
|
|
|
@@ -6,11 +6,11 @@
|
|
|
|
|
|
#include <stddef.h>
|
|
|
#include <stdint.h>
|
|
|
-#include <algorithm>
|
|
|
#include <string>
|
|
|
#include <vector>
|
|
|
|
|
|
#include "base/rand_util.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/strings/string_number_conversions.h"
|
|
|
#include "base/strings/string_util.h"
|
|
|
#include "base/time/time.h"
|
|
|
@@ -48,7 +48,7 @@ void Timing(const size_t len) {
|
|
|
utime[i] = TimeTicks::Now() - start;
|
|
|
total_test_time += utime[i];
|
|
|
}
|
|
|
- std::sort(utime.begin(), utime.end());
|
|
|
+ ranges::sort(utime);
|
|
|
}
|
|
|
|
|
|
reporter.AddResult(kMetricRuntime, total_test_time.InMicrosecondsF());
|
|
|
@@ -67,8 +67,8 @@ void Timing(const size_t len) {
|
|
|
|
|
|
// Convert to a comma-separated string so we can report every data point.
|
|
|
std::vector<std::string> rate_strings(utime.size());
|
|
|
- std::transform(utime.cbegin(), utime.cend(), rate_strings.begin(),
|
|
|
- [rate](const auto& t) { return NumberToString(rate(t)); });
|
|
|
+ ranges::transform(utime, rate_strings.begin(),
|
|
|
+ [rate](const auto& t) { return NumberToString(rate(t)); });
|
|
|
reporter.AddResultList(kMetricThroughput, JoinString(rate_strings, ","));
|
|
|
}
|
|
|
|
|
|
diff -up chromium-86.0.4240.111/base/i18n/break_iterator_unittest.cc.a61fb57e chromium-86.0.4240.111/base/i18n/break_iterator_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/i18n/break_iterator_unittest.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/i18n/break_iterator_unittest.cc 2020-10-21 17:11:20.006228768 -0400
|
|
|
@@ -7,6 +7,7 @@
|
|
|
#include <stddef.h>
|
|
|
#include <vector>
|
|
|
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/strings/string_piece.h"
|
|
|
#include "base/strings/string_util.h"
|
|
|
@@ -414,8 +415,7 @@ TEST(BreakIteratorTest, IsSentenceBounda
|
|
|
sentence_breaks.push_back(24);
|
|
|
sentence_breaks.push_back(42);
|
|
|
for (size_t i = 0; i < str.size(); i++) {
|
|
|
- if (std::find(sentence_breaks.begin(), sentence_breaks.end(), i) !=
|
|
|
- sentence_breaks.end()) {
|
|
|
+ if (ranges::find(sentence_breaks, i) != sentence_breaks.end()) {
|
|
|
EXPECT_TRUE(iter.IsSentenceBoundary(i)) << " at index=" << i;
|
|
|
} else {
|
|
|
EXPECT_FALSE(iter.IsSentenceBoundary(i)) << " at index=" << i;
|
|
|
diff -up chromium-86.0.4240.111/base/json/json_parser.cc.a61fb57e chromium-86.0.4240.111/base/json/json_parser.cc
|
|
|
--- chromium-86.0.4240.111/base/json/json_parser.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/json/json_parser.cc 2020-10-21 17:11:20.006228768 -0400
|
|
|
@@ -13,6 +13,7 @@
|
|
|
#include "base/macros.h"
|
|
|
#include "base/notreached.h"
|
|
|
#include "base/numerics/safe_conversions.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/strings/string_number_conversions.h"
|
|
|
#include "base/strings/string_piece.h"
|
|
|
#include "base/strings/string_util.h"
|
|
|
@@ -441,7 +442,7 @@ Optional<Value> JSONParser::ConsumeDicti
|
|
|
ConsumeChar(); // Closing '}'.
|
|
|
// Reverse |dict_storage| to keep the last of elements with the same key in
|
|
|
// the input.
|
|
|
- std::reverse(dict_storage.begin(), dict_storage.end());
|
|
|
+ ranges::reverse(dict_storage);
|
|
|
return Value(Value::DictStorage(std::move(dict_storage)));
|
|
|
}
|
|
|
|
|
|
diff -up chromium-86.0.4240.111/base/memory/platform_shared_memory_region_unittest.cc.a61fb57e chromium-86.0.4240.111/base/memory/platform_shared_memory_region_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/memory/platform_shared_memory_region_unittest.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/memory/platform_shared_memory_region_unittest.cc 2020-10-21 17:11:20.006228768 -0400
|
|
|
@@ -7,6 +7,7 @@
|
|
|
#include "base/check.h"
|
|
|
#include "base/memory/shared_memory_mapping.h"
|
|
|
#include "base/process/process_metrics.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/system/sys_info.h"
|
|
|
#include "base/test/gtest_util.h"
|
|
|
#include "base/test/test_shared_memory_util.h"
|
|
|
@@ -250,11 +251,10 @@ void CheckReadOnlyMapProtection(void* ad
|
|
|
ASSERT_TRUE(base::debug::ReadProcMaps(&proc_maps));
|
|
|
std::vector<base::debug::MappedMemoryRegion> regions;
|
|
|
ASSERT_TRUE(base::debug::ParseProcMaps(proc_maps, ®ions));
|
|
|
- auto it =
|
|
|
- std::find_if(regions.begin(), regions.end(),
|
|
|
- [addr](const base::debug::MappedMemoryRegion& region) {
|
|
|
- return region.start == reinterpret_cast<uintptr_t>(addr);
|
|
|
- });
|
|
|
+ auto it = ranges::find_if(
|
|
|
+ regions, [addr](const base::debug::MappedMemoryRegion& region) {
|
|
|
+ return region.start == reinterpret_cast<uintptr_t>(addr);
|
|
|
+ });
|
|
|
ASSERT_TRUE(it != regions.end());
|
|
|
// PROT_READ may imply PROT_EXEC on some architectures, so just check that
|
|
|
// permissions don't contain PROT_WRITE bit.
|
|
|
diff -up chromium-86.0.4240.111/base/memory/shared_memory_mapping_unittest.cc.a61fb57e chromium-86.0.4240.111/base/memory/shared_memory_mapping_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/memory/shared_memory_mapping_unittest.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/memory/shared_memory_mapping_unittest.cc 2020-10-21 17:11:20.007228776 -0400
|
|
|
@@ -6,12 +6,12 @@
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <limits>
|
|
|
|
|
|
#include "base/containers/span.h"
|
|
|
#include "base/memory/read_only_shared_memory_region.h"
|
|
|
#include "base/memory/writable_shared_memory_region.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/test/metrics/histogram_tester.h"
|
|
|
#include "build/build_config.h"
|
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
|
@@ -67,7 +67,7 @@ TEST_F(SharedMemoryMappingTest, SpanWith
|
|
|
span<const uint32_t> read_span = read_mapping_.GetMemoryAsSpan<uint32_t>();
|
|
|
ASSERT_EQ(2u, read_span.size());
|
|
|
|
|
|
- std::fill(write_span.begin(), write_span.end(), 0);
|
|
|
+ ranges::fill(write_span, 0);
|
|
|
EXPECT_EQ(0u, read_span[0]);
|
|
|
EXPECT_EQ(0u, read_span[1]);
|
|
|
|
|
|
@@ -92,7 +92,7 @@ TEST_F(SharedMemoryMappingTest, SpanWith
|
|
|
span<const uint32_t> read_span_2 = read_mapping_.GetMemoryAsSpan<uint32_t>(1);
|
|
|
ASSERT_EQ(1u, read_span_2.size());
|
|
|
|
|
|
- std::fill(write_span.begin(), write_span.end(), 0);
|
|
|
+ ranges::fill(write_span, 0);
|
|
|
EXPECT_EQ(0u, read_span[0]);
|
|
|
EXPECT_EQ(0u, read_span[1]);
|
|
|
EXPECT_EQ(0u, read_span_2[0]);
|
|
|
@@ -103,7 +103,7 @@ TEST_F(SharedMemoryMappingTest, SpanWith
|
|
|
EXPECT_EQ(0x08070605u, read_span[1]);
|
|
|
EXPECT_EQ(0x04030201u, read_span_2[0]);
|
|
|
|
|
|
- std::fill(write_span_2.begin(), write_span_2.end(), 0);
|
|
|
+ ranges::fill(write_span_2, 0);
|
|
|
EXPECT_EQ(0u, read_span[0]);
|
|
|
EXPECT_EQ(0x08070605u, read_span[1]);
|
|
|
EXPECT_EQ(0u, read_span_2[0]);
|
|
|
diff -up chromium-86.0.4240.111/base/metrics/histogram.cc.a61fb57e chromium-86.0.4240.111/base/metrics/histogram.cc
|
|
|
--- chromium-86.0.4240.111/base/metrics/histogram.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/metrics/histogram.cc 2020-10-21 17:11:20.008228785 -0400
|
|
|
@@ -13,7 +13,6 @@
|
|
|
#include <limits.h>
|
|
|
#include <math.h>
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <string>
|
|
|
#include <utility>
|
|
|
|
|
|
@@ -29,6 +28,7 @@
|
|
|
#include "base/metrics/sample_vector.h"
|
|
|
#include "base/metrics/statistics_recorder.h"
|
|
|
#include "base/pickle.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/strings/string_util.h"
|
|
|
#include "base/strings/stringprintf.h"
|
|
|
#include "base/strings/utf_string_conversions.h"
|
|
|
@@ -1248,8 +1248,8 @@ class CustomHistogram::Factory : public
|
|
|
std::vector<int> ranges = *custom_ranges_;
|
|
|
ranges.push_back(0); // Ensure we have a zero value.
|
|
|
ranges.push_back(HistogramBase::kSampleType_MAX);
|
|
|
- std::sort(ranges.begin(), ranges.end());
|
|
|
- ranges.erase(std::unique(ranges.begin(), ranges.end()), ranges.end());
|
|
|
+ ranges::sort(ranges);
|
|
|
+ ranges.erase(ranges::unique(ranges), ranges.end());
|
|
|
|
|
|
BucketRanges* bucket_ranges = new BucketRanges(ranges.size());
|
|
|
for (uint32_t i = 0; i < ranges.size(); i++) {
|
|
|
diff -up chromium-86.0.4240.111/base/metrics/statistics_recorder.cc.a61fb57e chromium-86.0.4240.111/base/metrics/statistics_recorder.cc
|
|
|
--- chromium-86.0.4240.111/base/metrics/statistics_recorder.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/metrics/statistics_recorder.cc 2020-10-21 17:11:20.008228785 -0400
|
|
|
@@ -16,6 +16,7 @@
|
|
|
#include "base/metrics/metrics_hashes.h"
|
|
|
#include "base/metrics/persistent_histogram_allocator.h"
|
|
|
#include "base/metrics/record_histogram_checker.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/strings/stringprintf.h"
|
|
|
#include "base/values.h"
|
|
|
@@ -366,7 +367,7 @@ StatisticsRecorder::Histograms Statistic
|
|
|
|
|
|
// static
|
|
|
StatisticsRecorder::Histograms StatisticsRecorder::Sort(Histograms histograms) {
|
|
|
- std::sort(histograms.begin(), histograms.end(), &HistogramNameLesser);
|
|
|
+ ranges::sort(histograms, &HistogramNameLesser);
|
|
|
return histograms;
|
|
|
}
|
|
|
|
|
|
@@ -376,12 +377,12 @@ StatisticsRecorder::Histograms Statistic
|
|
|
const std::string& query) {
|
|
|
// Need a C-string query for comparisons against C-string histogram name.
|
|
|
const char* const query_string = query.c_str();
|
|
|
- histograms.erase(std::remove_if(histograms.begin(), histograms.end(),
|
|
|
- [query_string](const HistogramBase* const h) {
|
|
|
- return !strstr(h->histogram_name(),
|
|
|
- query_string);
|
|
|
- }),
|
|
|
- histograms.end());
|
|
|
+ histograms.erase(
|
|
|
+ ranges::remove_if(histograms,
|
|
|
+ [query_string](const HistogramBase* const h) {
|
|
|
+ return !strstr(h->histogram_name(), query_string);
|
|
|
+ }),
|
|
|
+ histograms.end());
|
|
|
return histograms;
|
|
|
}
|
|
|
|
|
|
@@ -389,10 +390,11 @@ StatisticsRecorder::Histograms Statistic
|
|
|
StatisticsRecorder::Histograms StatisticsRecorder::NonPersistent(
|
|
|
Histograms histograms) {
|
|
|
histograms.erase(
|
|
|
- std::remove_if(histograms.begin(), histograms.end(),
|
|
|
- [](const HistogramBase* const h) {
|
|
|
- return (h->flags() & HistogramBase::kIsPersistent) != 0;
|
|
|
- }),
|
|
|
+ ranges::remove_if(histograms,
|
|
|
+ [](const HistogramBase* const h) {
|
|
|
+ return (h->flags() & HistogramBase::kIsPersistent) !=
|
|
|
+ 0;
|
|
|
+ }),
|
|
|
histograms.end());
|
|
|
return histograms;
|
|
|
}
|
|
|
diff -up chromium-86.0.4240.111/base/observer_list.h.a61fb57e chromium-86.0.4240.111/base/observer_list.h
|
|
|
--- chromium-86.0.4240.111/base/observer_list.h.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/observer_list.h 2020-10-21 17:11:20.009228794 -0400
|
|
|
@@ -18,6 +18,7 @@
|
|
|
#include "base/macros.h"
|
|
|
#include "base/notreached.h"
|
|
|
#include "base/observer_list_internal.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/sequence_checker.h"
|
|
|
#include "base/stl_util.h"
|
|
|
|
|
|
@@ -279,9 +280,8 @@ class ObserverList {
|
|
|
// not in this list.
|
|
|
void RemoveObserver(const ObserverType* obs) {
|
|
|
DCHECK(obs);
|
|
|
- const auto it =
|
|
|
- std::find_if(observers_.begin(), observers_.end(),
|
|
|
- [obs](const auto& o) { return o.IsEqual(obs); });
|
|
|
+ const auto it = ranges::find_if(
|
|
|
+ observers_, [obs](const auto& o) { return o.IsEqual(obs); });
|
|
|
if (it == observers_.end())
|
|
|
return;
|
|
|
|
|
|
@@ -300,9 +300,9 @@ class ObserverList {
|
|
|
// probably DCHECK, but some client code currently does pass null.
|
|
|
if (obs == nullptr)
|
|
|
return false;
|
|
|
- return std::find_if(observers_.begin(), observers_.end(),
|
|
|
- [obs](const auto& o) { return o.IsEqual(obs); }) !=
|
|
|
- observers_.end();
|
|
|
+ return ranges::find_if(observers_, [obs](const auto& o) {
|
|
|
+ return o.IsEqual(obs);
|
|
|
+ }) != observers_.end();
|
|
|
}
|
|
|
|
|
|
// Removes all the observers from this list.
|
|
|
diff -up chromium-86.0.4240.111/base/process/process_metrics_unittest.cc.a61fb57e chromium-86.0.4240.111/base/process/process_metrics_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/process/process_metrics_unittest.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/process/process_metrics_unittest.cc 2020-10-21 17:11:20.009228794 -0400
|
|
|
@@ -19,6 +19,7 @@
|
|
|
#include "base/macros.h"
|
|
|
#include "base/memory/shared_memory_mapping.h"
|
|
|
#include "base/memory/writable_shared_memory_region.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/strings/string_number_conversions.h"
|
|
|
#include "base/strings/string_util.h"
|
|
|
#include "base/strings/stringprintf.h"
|
|
|
@@ -781,13 +782,13 @@ TEST(ProcessMetricsTestLinux, GetCumulat
|
|
|
|
|
|
// Should have at least the test runner thread and the thread spawned above.
|
|
|
EXPECT_GE(prev_thread_times.size(), 2u);
|
|
|
- EXPECT_TRUE(std::any_of(
|
|
|
- prev_thread_times.begin(), prev_thread_times.end(),
|
|
|
+ EXPECT_TRUE(ranges::any_of(
|
|
|
+ prev_thread_times,
|
|
|
[&thread1](const std::pair<PlatformThreadId, base::TimeDelta>& entry) {
|
|
|
return entry.first == thread1.GetThreadId();
|
|
|
}));
|
|
|
- EXPECT_TRUE(std::any_of(
|
|
|
- prev_thread_times.begin(), prev_thread_times.end(),
|
|
|
+ EXPECT_TRUE(ranges::any_of(
|
|
|
+ prev_thread_times,
|
|
|
[](const std::pair<PlatformThreadId, base::TimeDelta>& entry) {
|
|
|
return entry.first == base::PlatformThread::CurrentId();
|
|
|
}));
|
|
|
@@ -803,16 +804,16 @@ TEST(ProcessMetricsTestLinux, GetCumulat
|
|
|
|
|
|
// The stopped thread may still be reported until the kernel cleans it up.
|
|
|
EXPECT_GE(prev_thread_times.size(), 1u);
|
|
|
- EXPECT_TRUE(std::any_of(
|
|
|
- current_thread_times.begin(), current_thread_times.end(),
|
|
|
+ EXPECT_TRUE(ranges::any_of(
|
|
|
+ current_thread_times,
|
|
|
[](const std::pair<PlatformThreadId, base::TimeDelta>& entry) {
|
|
|
return entry.first == base::PlatformThread::CurrentId();
|
|
|
}));
|
|
|
|
|
|
// Reported times should not decrease.
|
|
|
for (const auto& entry : current_thread_times) {
|
|
|
- auto prev_it = std::find_if(
|
|
|
- prev_thread_times.begin(), prev_thread_times.end(),
|
|
|
+ auto prev_it = ranges::find_if(
|
|
|
+ prev_thread_times,
|
|
|
[&entry](
|
|
|
const std::pair<PlatformThreadId, base::TimeDelta>& prev_entry) {
|
|
|
return entry.first == prev_entry.first;
|
|
|
@@ -862,8 +863,8 @@ TEST(ProcessMetricsTestLinux, GetPerThre
|
|
|
|
|
|
// Reported times should not decrease.
|
|
|
for (const auto& entry : current_thread_times) {
|
|
|
- auto prev_it = std::find_if(
|
|
|
- prev_thread_times.begin(), prev_thread_times.end(),
|
|
|
+ auto prev_it = ranges::find_if(
|
|
|
+ prev_thread_times,
|
|
|
[&entry](const ProcessMetrics::ThreadTimeInState& prev_entry) {
|
|
|
return entry.thread_id == prev_entry.thread_id &&
|
|
|
entry.core_type == prev_entry.core_type &&
|
|
|
diff -up chromium-86.0.4240.111/base/profiler/arm_cfi_table.cc.a61fb57e chromium-86.0.4240.111/base/profiler/arm_cfi_table.cc
|
|
|
--- chromium-86.0.4240.111/base/profiler/arm_cfi_table.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/profiler/arm_cfi_table.cc 2020-10-21 17:11:20.009228794 -0400
|
|
|
@@ -4,7 +4,7 @@
|
|
|
|
|
|
#include "base/profiler/arm_cfi_table.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
|
|
|
namespace base {
|
|
|
|
|
|
@@ -91,8 +91,7 @@ Optional<ArmCFITable::FrameEntry> ArmCFI
|
|
|
// Find the required function address in UNW_INDEX as the last function lower
|
|
|
// or equal to |address| (the value right before the result of upper_bound(),
|
|
|
// if any).
|
|
|
- auto func_it = std::upper_bound(function_addresses_.begin(),
|
|
|
- function_addresses_.end(), address);
|
|
|
+ auto func_it = ranges::upper_bound(function_addresses_, address);
|
|
|
// If no function comes before |address|, no CFI entry is returned.
|
|
|
if (func_it == function_addresses_.begin())
|
|
|
return nullopt;
|
|
|
@@ -157,4 +156,4 @@ Optional<ArmCFITable::FrameEntry> ArmCFI
|
|
|
return last_frame_entry;
|
|
|
}
|
|
|
|
|
|
-} // namespace base
|
|
|
\ No newline at end of file
|
|
|
+} // namespace base
|
|
|
diff -up chromium-86.0.4240.111/base/profiler/metadata_recorder_unittest.cc.a61fb57e chromium-86.0.4240.111/base/profiler/metadata_recorder_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/profiler/metadata_recorder_unittest.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/profiler/metadata_recorder_unittest.cc 2020-10-21 17:11:20.010228802 -0400
|
|
|
@@ -4,6 +4,7 @@
|
|
|
|
|
|
#include "base/profiler/metadata_recorder.h"
|
|
|
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/test/gtest_util.h"
|
|
|
#include "base/test/metrics/histogram_tester.h"
|
|
|
#include "testing/gmock/include/gmock/gmock.h"
|
|
|
@@ -213,7 +214,7 @@ TEST(MetadataRecorderTest, ReclaimInacti
|
|
|
}
|
|
|
|
|
|
MetadataRecorder::ItemArray items_arr;
|
|
|
- std::copy(items_set.begin(), items_set.end(), items_arr.begin());
|
|
|
+ ranges::copy(items_set, items_arr.begin());
|
|
|
|
|
|
MetadataRecorder::ItemArray recorder_items;
|
|
|
size_t recorder_item_count =
|
|
|
diff -up chromium-86.0.4240.111/base/profiler/module_cache.cc.a61fb57e chromium-86.0.4240.111/base/profiler/module_cache.cc
|
|
|
--- chromium-86.0.4240.111/base/profiler/module_cache.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/profiler/module_cache.cc 2020-10-21 17:11:20.010228802 -0400
|
|
|
@@ -4,10 +4,11 @@
|
|
|
|
|
|
#include "base/profiler/module_cache.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <iterator>
|
|
|
#include <utility>
|
|
|
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
+
|
|
|
namespace base {
|
|
|
|
|
|
namespace {
|
|
|
diff -up chromium-86.0.4240.111/base/profiler/stack_sampler_impl.cc.a61fb57e chromium-86.0.4240.111/base/profiler/stack_sampler_impl.cc
|
|
|
--- chromium-86.0.4240.111/base/profiler/stack_sampler_impl.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/profiler/stack_sampler_impl.cc 2020-10-21 17:11:20.010228802 -0400
|
|
|
@@ -16,6 +16,7 @@
|
|
|
#include "base/profiler/stack_copier.h"
|
|
|
#include "base/profiler/suspendable_thread_delegate.h"
|
|
|
#include "base/profiler/unwinder.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "build/build_config.h"
|
|
|
|
|
|
// IMPORTANT NOTE: Some functions within this implementation are invoked while
|
|
|
@@ -161,11 +162,10 @@ std::vector<Frame> StackSamplerImpl::Wal
|
|
|
do {
|
|
|
// Choose an authoritative unwinder for the current module. Use the first
|
|
|
// unwinder that thinks it can unwind from the current frame.
|
|
|
- auto unwinder =
|
|
|
- std::find_if(unwinders.begin(), unwinders.end(),
|
|
|
- [&stack](const std::unique_ptr<Unwinder>& unwinder) {
|
|
|
- return unwinder->CanUnwindFrom(stack.back());
|
|
|
- });
|
|
|
+ auto unwinder = ranges::find_if(
|
|
|
+ unwinders, [&stack](const std::unique_ptr<Unwinder>& unwinder) {
|
|
|
+ return unwinder->CanUnwindFrom(stack.back());
|
|
|
+ });
|
|
|
if (unwinder == unwinders.end())
|
|
|
return stack;
|
|
|
|
|
|
diff -up chromium-86.0.4240.111/base/profiler/stack_sampling_profiler_unittest.cc.a61fb57e chromium-86.0.4240.111/base/profiler/stack_sampling_profiler_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/profiler/stack_sampling_profiler_unittest.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/profiler/stack_sampling_profiler_unittest.cc 2020-10-21 17:11:20.011228811 -0400
|
|
|
@@ -5,7 +5,6 @@
|
|
|
#include <stddef.h>
|
|
|
#include <stdint.h>
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <cstdlib>
|
|
|
#include <memory>
|
|
|
#include <set>
|
|
|
@@ -25,6 +24,7 @@
|
|
|
#include "base/profiler/stack_sampling_profiler.h"
|
|
|
#include "base/profiler/stack_sampling_profiler_test_util.h"
|
|
|
#include "base/profiler/unwinder.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/run_loop.h"
|
|
|
#include "base/scoped_native_library.h"
|
|
|
#include "base/stl_util.h"
|
|
|
@@ -269,10 +269,10 @@ size_t WaitForSamplingComplete(
|
|
|
const std::vector<std::unique_ptr<TestProfilerInfo>>& infos) {
|
|
|
// Map unique_ptrs to something that WaitMany can accept.
|
|
|
std::vector<WaitableEvent*> sampling_completed_rawptrs(infos.size());
|
|
|
- std::transform(infos.begin(), infos.end(), sampling_completed_rawptrs.begin(),
|
|
|
- [](const std::unique_ptr<TestProfilerInfo>& info) {
|
|
|
- return &info.get()->completed;
|
|
|
- });
|
|
|
+ ranges::transform(infos, sampling_completed_rawptrs.begin(),
|
|
|
+ [](const std::unique_ptr<TestProfilerInfo>& info) {
|
|
|
+ return &info.get()->completed;
|
|
|
+ });
|
|
|
// Wait for one profiler to finish.
|
|
|
return WaitableEvent::WaitMany(sampling_completed_rawptrs.data(),
|
|
|
sampling_completed_rawptrs.size());
|
|
|
diff -up chromium-86.0.4240.111/base/ranges/algorithm.h.a61fb57e chromium-86.0.4240.111/base/ranges/algorithm.h
|
|
|
--- chromium-86.0.4240.111/base/ranges/algorithm.h.a61fb57e 2020-10-21 17:44:59.179014291 -0400
|
|
|
+++ chromium-86.0.4240.111/base/ranges/algorithm.h 2020-10-21 17:43:40.094374195 -0400
|
|
|
@@ -0,0 +1,4965 @@
|
|
|
+// Copyright 2020 The Chromium Authors. All rights reserved.
|
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
|
+// found in the LICENSE file.
|
|
|
+
|
|
|
+#ifndef BASE_RANGES_ALGORITHM_H_
|
|
|
+#define BASE_RANGES_ALGORITHM_H_
|
|
|
+
|
|
|
+#include <algorithm>
|
|
|
+#include <initializer_list>
|
|
|
+#include <iterator>
|
|
|
+#include <type_traits>
|
|
|
+#include <utility>
|
|
|
+
|
|
|
+#include "base/ranges/functional.h"
|
|
|
+#include "base/ranges/ranges.h"
|
|
|
+#include "base/stl_util.h"
|
|
|
+#include "base/template_util.h"
|
|
|
+
|
|
|
+namespace base {
|
|
|
+
|
|
|
+namespace internal {
|
|
|
+
|
|
|
+// Returns a transformed version of the unary predicate `pred` applying `proj`
|
|
|
+// to its argument before invoking `pred` on it.
|
|
|
+// Ensures that the return type of `invoke(pred, ...)` is convertible to bool.
|
|
|
+template <typename Pred, typename Proj>
|
|
|
+constexpr auto ProjectedUnaryPredicate(Pred& pred, Proj& proj) noexcept {
|
|
|
+ return [&pred, &proj](auto&& arg) -> bool {
|
|
|
+ return base::invoke(pred,
|
|
|
+ base::invoke(proj, std::forward<decltype(arg)>(arg)));
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+// Returns a transformed version of the binary predicate `pred` applying `proj1`
|
|
|
+// and `proj2` to its arguments before invoking `pred` on them.
|
|
|
+//
|
|
|
+// Provides an opt-in to considers all four permutations of projections and
|
|
|
+// argument types. This is sometimes necessary to allow usage with legacy
|
|
|
+// non-ranges std:: algorithms that don't support projections.
|
|
|
+//
|
|
|
+// These permutations are assigned different priorities to break ambiguities in
|
|
|
+// case several permutations are possible, e.g. when Proj1 and Proj2 are the
|
|
|
+// same type.
|
|
|
+//
|
|
|
+// Note that even when opting in to using all permutations of projections,
|
|
|
+// calling code should still ensure that the canonical mapping of {Proj1, Proj2}
|
|
|
+// to {LHS, RHS} compiles for all members of the range. This can be done by
|
|
|
+// adding the following constraint:
|
|
|
+//
|
|
|
+// typename = indirect_result_t<Pred&,
|
|
|
+// projected<iterator_t<Range1>, Proj1>,
|
|
|
+// projected<iterator_t<Range2>, Proj2>>
|
|
|
+//
|
|
|
+// Ensures that the return type of `invoke(pred, ...)` is convertible to bool.
|
|
|
+template <typename Pred, typename Proj1, typename Proj2, bool kPermute = false>
|
|
|
+class BinaryPredicateProjector {
|
|
|
+ public:
|
|
|
+ constexpr BinaryPredicateProjector(Pred& pred, Proj1& proj1, Proj2& proj2)
|
|
|
+ : pred_(pred), proj1_(proj1), proj2_(proj2) {}
|
|
|
+
|
|
|
+ private:
|
|
|
+ template <typename ProjT, typename ProjU, typename T, typename U>
|
|
|
+ using InvokeResult = invoke_result_t<Pred&,
|
|
|
+ invoke_result_t<ProjT&, T&&>,
|
|
|
+ invoke_result_t<ProjU&, U&&>>;
|
|
|
+
|
|
|
+ template <typename T, typename U, typename = InvokeResult<Proj1, Proj2, T, U>>
|
|
|
+ constexpr std::pair<Proj1&, Proj2&> GetProjs(priority_tag<3>) const {
|
|
|
+ return {proj1_, proj2_};
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T,
|
|
|
+ typename U,
|
|
|
+ bool LazyPermute = kPermute,
|
|
|
+ typename = std::enable_if_t<LazyPermute>,
|
|
|
+ typename = InvokeResult<Proj2, Proj1, T, U>>
|
|
|
+ constexpr std::pair<Proj2&, Proj1&> GetProjs(priority_tag<2>) const {
|
|
|
+ return {proj2_, proj1_};
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T,
|
|
|
+ typename U,
|
|
|
+ bool LazyPermute = kPermute,
|
|
|
+ typename = std::enable_if_t<LazyPermute>,
|
|
|
+ typename = InvokeResult<Proj1, Proj1, T, U>>
|
|
|
+ constexpr std::pair<Proj1&, Proj1&> GetProjs(priority_tag<1>) const {
|
|
|
+ return {proj1_, proj1_};
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T,
|
|
|
+ typename U,
|
|
|
+ bool LazyPermute = kPermute,
|
|
|
+ typename = std::enable_if_t<LazyPermute>,
|
|
|
+ typename = InvokeResult<Proj2, Proj2, T, U>>
|
|
|
+ constexpr std::pair<Proj2&, Proj2&> GetProjs(priority_tag<0>) const {
|
|
|
+ return {proj2_, proj2_};
|
|
|
+ }
|
|
|
+
|
|
|
+ public:
|
|
|
+ template <typename T, typename U>
|
|
|
+ constexpr bool operator()(T&& lhs, U&& rhs) const {
|
|
|
+ auto projs = GetProjs<T, U>(priority_tag<3>());
|
|
|
+ return base::invoke(pred_, base::invoke(projs.first, std::forward<T>(lhs)),
|
|
|
+ base::invoke(projs.second, std::forward<U>(rhs)));
|
|
|
+ }
|
|
|
+
|
|
|
+ private:
|
|
|
+ Pred& pred_;
|
|
|
+ Proj1& proj1_;
|
|
|
+ Proj2& proj2_;
|
|
|
+};
|
|
|
+
|
|
|
+// Small wrappers around BinaryPredicateProjector to make the calling side more
|
|
|
+// readable.
|
|
|
+template <typename Pred, typename Proj1, typename Proj2>
|
|
|
+constexpr auto ProjectedBinaryPredicate(Pred& pred,
|
|
|
+ Proj1& proj1,
|
|
|
+ Proj2& proj2) noexcept {
|
|
|
+ return BinaryPredicateProjector<Pred, Proj1, Proj2>(pred, proj1, proj2);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Pred, typename Proj1, typename Proj2>
|
|
|
+constexpr auto PermutedProjectedBinaryPredicate(Pred& pred,
|
|
|
+ Proj1& proj1,
|
|
|
+ Proj2& proj2) noexcept {
|
|
|
+ return BinaryPredicateProjector<Pred, Proj1, Proj2, true>(pred, proj1, proj2);
|
|
|
+}
|
|
|
+
|
|
|
+// This alias is used below to restrict iterator based APIs to types for which
|
|
|
+// `iterator_category` and the pre-increment and post-increment operators are
|
|
|
+// defined. This is required in situations where otherwise an undesired overload
|
|
|
+// would be chosen, e.g. copy_if. In spirit this is similar to C++20's
|
|
|
+// std::input_or_output_iterator, a concept that each iterator should satisfy.
|
|
|
+template <typename Iter,
|
|
|
+ typename = decltype(++std::declval<Iter&>()),
|
|
|
+ typename = decltype(std::declval<Iter&>()++)>
|
|
|
+using iterator_category_t =
|
|
|
+ typename std::iterator_traits<Iter>::iterator_category;
|
|
|
+
|
|
|
+// This alias is used below to restrict range based APIs to types for which
|
|
|
+// `iterator_category_t` is defined for the underlying iterator. This is
|
|
|
+// required in situations where otherwise an undesired overload would be chosen,
|
|
|
+// e.g. transform. In spirit this is similar to C++20's std::ranges::range, a
|
|
|
+// concept that each range should satisfy.
|
|
|
+template <typename Range>
|
|
|
+using range_category_t = iterator_category_t<ranges::iterator_t<Range>>;
|
|
|
+
|
|
|
+} // namespace internal
|
|
|
+
|
|
|
+namespace ranges {
|
|
|
+
|
|
|
+// C++14 implementation of std::ranges::in_fun_result. Note the because C++14
|
|
|
+// lacks the `no_unique_address` attribute it is commented out.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/algorithms.results#:~:text=in_fun_result
|
|
|
+template <typename I, typename F>
|
|
|
+struct in_fun_result {
|
|
|
+ /* [[no_unique_address]] */ I in;
|
|
|
+ /* [[no_unique_address]] */ F fun;
|
|
|
+
|
|
|
+ template <typename I2,
|
|
|
+ typename F2,
|
|
|
+ std::enable_if_t<std::is_convertible<const I&, I2>{} &&
|
|
|
+ std::is_convertible<const F&, F2>{}>>
|
|
|
+ constexpr operator in_fun_result<I2, F2>() const& {
|
|
|
+ return {in, fun};
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename I2,
|
|
|
+ typename F2,
|
|
|
+ std::enable_if_t<std::is_convertible<I, I2>{} &&
|
|
|
+ std::is_convertible<F, F2>{}>>
|
|
|
+ constexpr operator in_fun_result<I2, F2>() && {
|
|
|
+ return {std::move(in), std::move(fun)};
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// TODO(crbug.com/1071094): Implement the other result types.
|
|
|
+
|
|
|
+// [alg.nonmodifying] Non-modifying sequence operations
|
|
|
+// Reference: https://wg21.link/alg.nonmodifying
|
|
|
+
|
|
|
+// [alg.all.of] All of
|
|
|
+// Reference: https://wg21.link/alg.all.of
|
|
|
+
|
|
|
+// Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
|
|
|
+//
|
|
|
+// Returns: `false` if `E(i)` is `false` for some iterator `i` in the range
|
|
|
+// `[first, last)`, and `true` otherwise.
|
|
|
+//
|
|
|
+// Complexity: At most `last - first` applications of the predicate and any
|
|
|
+// projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.all.of#:~:text=ranges::all_of(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>>
|
|
|
+constexpr bool all_of(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ for (; first != last; ++first) {
|
|
|
+ if (!base::invoke(pred, base::invoke(proj, *first)))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
|
|
|
+//
|
|
|
+// Returns: `false` if `E(i)` is `false` for some iterator `i` in `range`, and
|
|
|
+// `true` otherwise.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range)` applications of the predicate and any
|
|
|
+// projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.all.of#:~:text=ranges::all_of(R
|
|
|
+template <typename Range,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr bool all_of(Range&& range, Pred pred, Proj proj = {}) {
|
|
|
+ return ranges::all_of(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.any.of] Any of
|
|
|
+// Reference: https://wg21.link/alg.any.of
|
|
|
+
|
|
|
+// Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
|
|
|
+//
|
|
|
+// Returns: `true` if `E(i)` is `true` for some iterator `i` in the range
|
|
|
+// `[first, last)`, and `false` otherwise.
|
|
|
+//
|
|
|
+// Complexity: At most `last - first` applications of the predicate and any
|
|
|
+// projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.any.of#:~:text=ranges::any_of(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>>
|
|
|
+constexpr bool any_of(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ for (; first != last; ++first) {
|
|
|
+ if (base::invoke(pred, base::invoke(proj, *first)))
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
|
|
|
+//
|
|
|
+// Returns: `true` if `E(i)` is `true` for some iterator `i` in `range`, and
|
|
|
+// `false` otherwise.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range)` applications of the predicate and any
|
|
|
+// projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.any.of#:~:text=ranges::any_of(R
|
|
|
+template <typename Range,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr bool any_of(Range&& range, Pred pred, Proj proj = {}) {
|
|
|
+ return ranges::any_of(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.none.of] None of
|
|
|
+// Reference: https://wg21.link/alg.none.of
|
|
|
+
|
|
|
+// Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
|
|
|
+//
|
|
|
+// Returns: `false` if `E(i)` is `true` for some iterator `i` in the range
|
|
|
+// `[first, last)`, and `true` otherwise.
|
|
|
+//
|
|
|
+// Complexity: At most `last - first` applications of the predicate and any
|
|
|
+// projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.none.of#:~:text=ranges::none_of(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>>
|
|
|
+constexpr bool none_of(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ for (; first != last; ++first) {
|
|
|
+ if (base::invoke(pred, base::invoke(proj, *first)))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `invoke(pred, invoke(proj, *i))`.
|
|
|
+//
|
|
|
+// Returns: `false` if `E(i)` is `true` for some iterator `i` in `range`, and
|
|
|
+// `true` otherwise.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range)` applications of the predicate and any
|
|
|
+// projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.none.of#:~:text=ranges::none_of(R
|
|
|
+template <typename Range,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr bool none_of(Range&& range, Pred pred, Proj proj = {}) {
|
|
|
+ return ranges::none_of(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.foreach] For each
|
|
|
+// Reference: https://wg21.link/alg.foreach
|
|
|
+
|
|
|
+// Reference: https://wg21.link/algorithm.syn#:~:text=for_each_result
|
|
|
+template <typename I, typename F>
|
|
|
+using for_each_result = in_fun_result<I, F>;
|
|
|
+
|
|
|
+// Effects: Calls `invoke(f, invoke(proj, *i))` for every iterator `i` in the
|
|
|
+// range `[first, last)`, starting from `first` and proceeding to `last - 1`.
|
|
|
+//
|
|
|
+// Returns: `{last, std::move(f)}`.
|
|
|
+//
|
|
|
+// Complexity: Applies `f` and `proj` exactly `last - first` times.
|
|
|
+//
|
|
|
+// Remarks: If `f` returns a result, the result is ignored.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.foreach#:~:text=ranges::for_each(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename Fun,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>>
|
|
|
+constexpr auto for_each(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ Fun f,
|
|
|
+ Proj proj = {}) {
|
|
|
+ for (; first != last; ++first)
|
|
|
+ base::invoke(f, base::invoke(proj, *first));
|
|
|
+ return for_each_result<InputIterator, Fun>{first, std::move(f)};
|
|
|
+}
|
|
|
+
|
|
|
+// Effects: Calls `invoke(f, invoke(proj, *i))` for every iterator `i` in the
|
|
|
+// range `range`, starting from `begin(range)` and proceeding to `end(range) -
|
|
|
+// 1`.
|
|
|
+//
|
|
|
+// Returns: `{last, std::move(f)}`.
|
|
|
+//
|
|
|
+// Complexity: Applies `f` and `proj` exactly `size(range)` times.
|
|
|
+//
|
|
|
+// Remarks: If `f` returns a result, the result is ignored.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.foreach#:~:text=ranges::for_each(R
|
|
|
+template <typename Range,
|
|
|
+ typename Fun,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto for_each(Range&& range, Fun f, Proj proj = {}) {
|
|
|
+ return ranges::for_each(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(f), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Reference: https://wg21.link/algorithm.syn#:~:text=for_each_n_result
|
|
|
+template <typename I, typename F>
|
|
|
+using for_each_n_result = in_fun_result<I, F>;
|
|
|
+
|
|
|
+// Preconditions: `n >= 0` is `true`.
|
|
|
+//
|
|
|
+// Effects: Calls `invoke(f, invoke(proj, *i))` for every iterator `i` in the
|
|
|
+// range `[first, first + n)` in order.
|
|
|
+//
|
|
|
+// Returns: `{first + n, std::move(f)}`.
|
|
|
+//
|
|
|
+// Remarks: If `f` returns a result, the result is ignored.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.foreach#:~:text=ranges::for_each_n
|
|
|
+template <typename InputIterator,
|
|
|
+ typename Size,
|
|
|
+ typename Fun,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>>
|
|
|
+constexpr auto for_each_n(InputIterator first, Size n, Fun f, Proj proj = {}) {
|
|
|
+ while (n > 0) {
|
|
|
+ base::invoke(f, base::invoke(proj, *first));
|
|
|
+ ++first;
|
|
|
+ --n;
|
|
|
+ }
|
|
|
+
|
|
|
+ return for_each_n_result<InputIterator, Fun>{first, std::move(f)};
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.find] Find
|
|
|
+// Reference: https://wg21.link/alg.find
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(proj, *i) == value)`.
|
|
|
+//
|
|
|
+// Returns: The first iterator `i` in the range `[first, last)` for which `E(i)`
|
|
|
+// is `true`. Returns `last` if no such iterator is found.
|
|
|
+//
|
|
|
+// Complexity: At most `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.find#:~:text=ranges::find(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>>
|
|
|
+constexpr auto find(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ const T& value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ // Note: In order to be able to apply `proj` to each element in [first, last)
|
|
|
+ // we are dispatching to std::find_if instead of std::find.
|
|
|
+ return std::find_if(first, last, [&proj, &value](auto&& lhs) {
|
|
|
+ return base::invoke(proj, std::forward<decltype(lhs)>(lhs)) == value;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(proj, *i) == value)`.
|
|
|
+//
|
|
|
+// Returns: The first iterator `i` in `range` for which `E(i)` is `true`.
|
|
|
+// Returns `end(range)` if no such iterator is found.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range)` applications of the corresponding predicate
|
|
|
+// and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.find#:~:text=ranges::find(R
|
|
|
+template <typename Range,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto find(Range&& range, const T& value, Proj proj = {}) {
|
|
|
+ return ranges::find(ranges::begin(range), ranges::end(range), value,
|
|
|
+ std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Returns: The first iterator `i` in the range `[first, last)` for which `E(i)`
|
|
|
+// is `true`. Returns `last` if no such iterator is found.
|
|
|
+//
|
|
|
+// Complexity: At most `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.find#:~:text=ranges::find_if(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>>
|
|
|
+constexpr auto find_if(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::find_if(first, last,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Returns: The first iterator `i` in `range` for which `E(i)` is `true`.
|
|
|
+// Returns `end(range)` if no such iterator is found.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range)` applications of the corresponding predicate
|
|
|
+// and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.find#:~:text=ranges::find_if(R
|
|
|
+template <typename Range,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto find_if(Range&& range, Pred pred, Proj proj = {}) {
|
|
|
+ return ranges::find_if(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(!invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Returns: The first iterator `i` in the range `[first, last)` for which `E(i)`
|
|
|
+// is `true`. Returns `last` if no such iterator is found.
|
|
|
+//
|
|
|
+// Complexity: At most `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.find#:~:text=ranges::find_if_not(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>>
|
|
|
+constexpr auto find_if_not(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::find_if_not(first, last,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(!invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Returns: The first iterator `i` in `range` for which `E(i)` is `true`.
|
|
|
+// Returns `end(range)` if no such iterator is found.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range)` applications of the corresponding predicate
|
|
|
+// and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.find#:~:text=ranges::find_if_not(R
|
|
|
+template <typename Range,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto find_if_not(Range&& range, Pred pred, Proj proj = {}) {
|
|
|
+ return ranges::find_if_not(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.find.end] Find end
|
|
|
+// Reference: https://wg21.link/alg.find.end
|
|
|
+
|
|
|
+// Let:
|
|
|
+// - `E(i,n)` be `invoke(pred, invoke(proj1, *(i + n)),
|
|
|
+// invoke(proj2, *(first2 + n)))`
|
|
|
+//
|
|
|
+// - `i` be `last1` if `[first2, last2)` is empty, or if
|
|
|
+// `(last2 - first2) > (last1 - first1)` is `true`, or if there is no iterator
|
|
|
+// in the range `[first1, last1 - (last2 - first2))` such that for every
|
|
|
+// non-negative integer `n < (last2 - first2)`, `E(i,n)` is `true`. Otherwise
|
|
|
+// `i` is the last such iterator in `[first1, last1 - (last2 - first2))`.
|
|
|
+//
|
|
|
+// Returns: `i`
|
|
|
+// Note: std::ranges::find_end(I1 first1,...) returns a range, rather than an
|
|
|
+// iterator. For simplicitly we match std::find_end's return type instead.
|
|
|
+//
|
|
|
+// Complexity:
|
|
|
+// At most `(last2 - first2) * (last1 - first1 - (last2 - first2) + 1)`
|
|
|
+// applications of the corresponding predicate and any projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.find.end#:~:text=ranges::find_end(I1
|
|
|
+template <typename ForwardIterator1,
|
|
|
+ typename ForwardIterator2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator1>,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<ForwardIterator1, Proj1>,
|
|
|
+ projected<ForwardIterator2, Proj2>>>
|
|
|
+constexpr auto find_end(ForwardIterator1 first1,
|
|
|
+ ForwardIterator1 last1,
|
|
|
+ ForwardIterator2 first2,
|
|
|
+ ForwardIterator2 last2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return std::find_end(first1, last1, first2, last2,
|
|
|
+ internal::ProjectedBinaryPredicate(pred, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Let:
|
|
|
+// - `E(i,n)` be `invoke(pred, invoke(proj1, *(i + n)),
|
|
|
+// invoke(proj2, *(first2 + n)))`
|
|
|
+//
|
|
|
+// - `i` be `end(range1)` if `range2` is empty, or if
|
|
|
+// `size(range2) > size(range1)` is `true`, or if there is no iterator in the
|
|
|
+// range `[begin(range1), end(range1) - size(range2))` such that for every
|
|
|
+// non-negative integer `n < size(range2)`, `E(i,n)` is `true`. Otherwise `i`
|
|
|
+// is the last such iterator in `[begin(range1), end(range1) - size(range2))`.
|
|
|
+//
|
|
|
+// Returns: `i`
|
|
|
+// Note: std::ranges::find_end(R1&& r1,...) returns a range, rather than an
|
|
|
+// iterator. For simplicitly we match std::find_end's return type instead.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range2) * (size(range1) - size(range2) + 1)`
|
|
|
+// applications of the corresponding predicate and any projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.find.end#:~:text=ranges::find_end(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>>
|
|
|
+constexpr auto find_end(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::find_end(ranges::begin(range1), ranges::end(range1),
|
|
|
+ ranges::begin(range2), ranges::end(range2),
|
|
|
+ std::move(pred), std::move(proj1), std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.find.first.of] Find first
|
|
|
+// Reference: https://wg21.link/alg.find.first.of
|
|
|
+
|
|
|
+// Let `E(i,j)` be `bool(invoke(pred, invoke(proj1, *i), invoke(proj2, *j)))`.
|
|
|
+//
|
|
|
+// Effects: Finds an element that matches one of a set of values.
|
|
|
+//
|
|
|
+// Returns: The first iterator `i` in the range `[first1, last1)` such that for
|
|
|
+// some iterator `j` in the range `[first2, last2)` `E(i,j)` holds. Returns
|
|
|
+// `last1` if `[first2, last2)` is empty or if no such iterator is found.
|
|
|
+//
|
|
|
+// Complexity: At most `(last1 - first1) * (last2 - first2)` applications of the
|
|
|
+// corresponding predicate and any projections.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.find.first.of#:~:text=ranges::find_first_of(I1
|
|
|
+template <typename ForwardIterator1,
|
|
|
+ typename ForwardIterator2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator1>,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<ForwardIterator1, Proj1>,
|
|
|
+ projected<ForwardIterator2, Proj2>>>
|
|
|
+constexpr auto find_first_of(ForwardIterator1 first1,
|
|
|
+ ForwardIterator1 last1,
|
|
|
+ ForwardIterator2 first2,
|
|
|
+ ForwardIterator2 last2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return std::find_first_of(
|
|
|
+ first1, last1, first2, last2,
|
|
|
+ internal::ProjectedBinaryPredicate(pred, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i,j)` be `bool(invoke(pred, invoke(proj1, *i), invoke(proj2, *j)))`.
|
|
|
+//
|
|
|
+// Effects: Finds an element that matches one of a set of values.
|
|
|
+//
|
|
|
+// Returns: The first iterator `i` in `range1` such that for some iterator `j`
|
|
|
+// in `range2` `E(i,j)` holds. Returns `end(range1)` if `range2` is empty or if
|
|
|
+// no such iterator is found.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range1) * size(range2)` applications of the
|
|
|
+// corresponding predicate and any projections.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.find.first.of#:~:text=ranges::find_first_of(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>>
|
|
|
+constexpr auto find_first_of(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::find_first_of(
|
|
|
+ ranges::begin(range1), ranges::end(range1), ranges::begin(range2),
|
|
|
+ ranges::end(range2), std::move(pred), std::move(proj1), std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.adjacent.find] Adjacent find
|
|
|
+// Reference: https://wg21.link/alg.adjacent.find
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i), invoke(proj, *(i + 1))))`.
|
|
|
+//
|
|
|
+// Returns: The first iterator `i` such that both `i` and `i + 1` are in the
|
|
|
+// range `[first, last)` for which `E(i)` holds. Returns `last` if no such
|
|
|
+// iterator is found.
|
|
|
+//
|
|
|
+// Complexity: Exactly `min((i - first) + 1, (last - first) - 1)` applications
|
|
|
+// of the corresponding predicate, where `i` is `adjacent_find`'s return value.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.adjacent.find#:~:text=ranges::adjacent_find(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto adjacent_find(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::adjacent_find(
|
|
|
+ first, last, internal::ProjectedBinaryPredicate(pred, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i), invoke(proj, *(i + 1))))`.
|
|
|
+//
|
|
|
+// Returns: The first iterator `i` such that both `i` and `i + 1` are in the
|
|
|
+// range `range` for which `E(i)` holds. Returns `end(range)` if no such
|
|
|
+// iterator is found.
|
|
|
+//
|
|
|
+// Complexity: Exactly `min((i - begin(range)) + 1, size(range) - 1)`
|
|
|
+// applications of the corresponding predicate, where `i` is `adjacent_find`'s
|
|
|
+// return value.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.adjacent.find#:~:text=ranges::adjacent_find(R
|
|
|
+template <typename Range,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto adjacent_find(Range&& range, Pred pred = {}, Proj proj = {}) {
|
|
|
+ return ranges::adjacent_find(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.count] Count
|
|
|
+// Reference: https://wg21.link/alg.count
|
|
|
+
|
|
|
+// Let `E(i)` be `invoke(proj, *i) == value`.
|
|
|
+//
|
|
|
+// Effects: Returns the number of iterators `i` in the range `[first, last)` for
|
|
|
+// which `E(i)` holds.
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.count#:~:text=ranges::count(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>>
|
|
|
+constexpr auto count(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ const T& value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ // Note: In order to be able to apply `proj` to each element in [first, last)
|
|
|
+ // we are dispatching to std::count_if instead of std::count.
|
|
|
+ return std::count_if(first, last, [&proj, &value](auto&& lhs) {
|
|
|
+ return base::invoke(proj, std::forward<decltype(lhs)>(lhs)) == value;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `invoke(proj, *i) == value`.
|
|
|
+//
|
|
|
+// Effects: Returns the number of iterators `i` in `range` for which `E(i)`
|
|
|
+// holds.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of the corresponding predicate
|
|
|
+// and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.count#:~:text=ranges::count(R
|
|
|
+template <typename Range,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto count(Range&& range, const T& value, Proj proj = {}) {
|
|
|
+ return ranges::count(ranges::begin(range), ranges::end(range), value,
|
|
|
+ std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Effects: Returns the number of iterators `i` in the range `[first, last)` for
|
|
|
+// which `E(i)` holds.
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.count#:~:text=ranges::count_if(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>>
|
|
|
+constexpr auto count_if(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::count_if(first, last,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Effects: Returns the number of iterators `i` in `range` for which `E(i)`
|
|
|
+// holds.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of the corresponding predicate
|
|
|
+// and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.count#:~:text=ranges::count_if(R
|
|
|
+template <typename Range,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto count_if(Range&& range, Pred pred, Proj proj = {}) {
|
|
|
+ return ranges::count_if(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [mismatch] Mismatch
|
|
|
+// Reference: https://wg21.link/mismatch
|
|
|
+
|
|
|
+// Let `E(n)` be `!invoke(pred, invoke(proj1, *(first1 + n)),
|
|
|
+// invoke(proj2, *(first2 + n)))`.
|
|
|
+//
|
|
|
+// Let `N` be `min(last1 - first1, last2 - first2)`.
|
|
|
+//
|
|
|
+// Returns: `{ first1 + n, first2 + n }`, where `n` is the smallest integer in
|
|
|
+// `[0, N)` such that `E(n)` holds, or `N` if no such integer exists.
|
|
|
+//
|
|
|
+// Complexity: At most `N` applications of the corresponding predicate and any
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/mismatch#:~:text=ranges::mismatch(I1
|
|
|
+template <typename ForwardIterator1,
|
|
|
+ typename ForwardIterator2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator1>,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<ForwardIterator1, Proj1>,
|
|
|
+ projected<ForwardIterator2, Proj2>>>
|
|
|
+constexpr auto mismatch(ForwardIterator1 first1,
|
|
|
+ ForwardIterator1 last1,
|
|
|
+ ForwardIterator2 first2,
|
|
|
+ ForwardIterator2 last2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return std::mismatch(first1, last1, first2, last2,
|
|
|
+ internal::ProjectedBinaryPredicate(pred, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(n)` be `!invoke(pred, invoke(proj1, *(begin(range1) + n)),
|
|
|
+// invoke(proj2, *(begin(range2) + n)))`.
|
|
|
+//
|
|
|
+// Let `N` be `min(size(range1), size(range2))`.
|
|
|
+//
|
|
|
+// Returns: `{ begin(range1) + n, begin(range2) + n }`, where `n` is the
|
|
|
+// smallest integer in `[0, N)` such that `E(n)` holds, or `N` if no such
|
|
|
+// integer exists.
|
|
|
+//
|
|
|
+// Complexity: At most `N` applications of the corresponding predicate and any
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/mismatch#:~:text=ranges::mismatch(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>>
|
|
|
+constexpr auto mismatch(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::mismatch(ranges::begin(range1), ranges::end(range1),
|
|
|
+ ranges::begin(range2), ranges::end(range2),
|
|
|
+ std::move(pred), std::move(proj1), std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.equal] Equal
|
|
|
+// Reference: https://wg21.link/alg.equal
|
|
|
+
|
|
|
+// Let `E(i)` be
|
|
|
+// `invoke(pred, invoke(proj1, *i), invoke(proj2, *(first2 + (i - first1))))`.
|
|
|
+//
|
|
|
+// Returns: If `last1 - first1 != last2 - first2`, return `false.` Otherwise
|
|
|
+// return `true` if `E(i)` holds for every iterator `i` in the range `[first1,
|
|
|
+// last1)`. Otherwise, returns `false`.
|
|
|
+//
|
|
|
+// Complexity: If the types of `first1`, `last1`, `first2`, and `last2` meet the
|
|
|
+// `RandomAccessIterator` requirements and `last1 - first1 != last2 - first2`,
|
|
|
+// then no applications of the corresponding predicate and each projection;
|
|
|
+// otherwise, at most `min(last1 - first1, last2 - first2)` applications of the
|
|
|
+// corresponding predicate and any projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.equal#:~:text=ranges::equal(I1
|
|
|
+template <typename ForwardIterator1,
|
|
|
+ typename ForwardIterator2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator1>,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<ForwardIterator1, Proj1>,
|
|
|
+ projected<ForwardIterator2, Proj2>>>
|
|
|
+constexpr bool equal(ForwardIterator1 first1,
|
|
|
+ ForwardIterator1 last1,
|
|
|
+ ForwardIterator2 first2,
|
|
|
+ ForwardIterator2 last2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return std::equal(first1, last1, first2, last2,
|
|
|
+ internal::ProjectedBinaryPredicate(pred, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be
|
|
|
+// `invoke(pred, invoke(proj1, *i),
|
|
|
+// invoke(proj2, *(begin(range2) + (i - begin(range1)))))`.
|
|
|
+//
|
|
|
+// Returns: If `size(range1) != size(range2)`, return `false.` Otherwise return
|
|
|
+// `true` if `E(i)` holds for every iterator `i` in `range1`. Otherwise, returns
|
|
|
+// `false`.
|
|
|
+//
|
|
|
+// Complexity: If the types of `begin(range1)`, `end(range1)`, `begin(range2)`,
|
|
|
+// and `end(range2)` meet the `RandomAccessIterator` requirements and
|
|
|
+// `size(range1) != size(range2)`, then no applications of the corresponding
|
|
|
+// predicate and each projection;
|
|
|
+// otherwise, at most `min(size(range1), size(range2))` applications of the
|
|
|
+// corresponding predicate and any projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.equal#:~:text=ranges::equal(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>>
|
|
|
+constexpr bool equal(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::equal(ranges::begin(range1), ranges::end(range1),
|
|
|
+ ranges::begin(range2), ranges::end(range2),
|
|
|
+ std::move(pred), std::move(proj1), std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.is.permutation] Is permutation
|
|
|
+// Reference: https://wg21.link/alg.is.permutation
|
|
|
+
|
|
|
+// Returns: If `last1 - first1 != last2 - first2`, return `false`. Otherwise
|
|
|
+// return `true` if there exists a permutation of the elements in the range
|
|
|
+// `[first2, last2)`, bounded by `[pfirst, plast)`, such that
|
|
|
+// `ranges::equal(first1, last1, pfirst, plast, pred, proj, proj)` returns
|
|
|
+// `true`; otherwise, returns `false`.
|
|
|
+//
|
|
|
+// Complexity: No applications of the corresponding predicate if
|
|
|
+// ForwardIterator1 and ForwardIterator2 meet the requirements of random access
|
|
|
+// iterators and `last1 - first1 != last2 - first2`. Otherwise, exactly
|
|
|
+// `last1 - first1` applications of the corresponding predicate and projections
|
|
|
+// if `ranges::equal(first1, last1, first2, last2, pred, proj, proj)` would
|
|
|
+// return true;
|
|
|
+// otherwise, at worst `O(N^2)`, where `N` has the value `last1 - first1`.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.is.permutation#:~:text=ranges::is_permutation(I1
|
|
|
+template <typename ForwardIterator1,
|
|
|
+ typename ForwardIterator2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator1>,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<ForwardIterator1, Proj1>,
|
|
|
+ projected<ForwardIterator2, Proj2>>>
|
|
|
+constexpr bool is_permutation(ForwardIterator1 first1,
|
|
|
+ ForwardIterator1 last1,
|
|
|
+ ForwardIterator2 first2,
|
|
|
+ ForwardIterator2 last2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ // Needs to opt-in to all permutations, since std::is_permutation expects
|
|
|
+ // pred(proj1(lhs), proj1(rhs)) to compile.
|
|
|
+ return std::is_permutation(
|
|
|
+ first1, last1, first2, last2,
|
|
|
+ internal::PermutedProjectedBinaryPredicate(pred, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: If `size(range1) != size(range2)`, return `false`. Otherwise return
|
|
|
+// `true` if there exists a permutation of the elements in `range2`, bounded by
|
|
|
+// `[pbegin, pend)`, such that
|
|
|
+// `ranges::equal(range1, [pbegin, pend), pred, proj, proj)` returns `true`;
|
|
|
+// otherwise, returns `false`.
|
|
|
+//
|
|
|
+// Complexity: No applications of the corresponding predicate if Range1 and
|
|
|
+// Range2 meet the requirements of random access ranges and
|
|
|
+// `size(range1) != size(range2)`. Otherwise, exactly `size(range1)`
|
|
|
+// applications of the corresponding predicate and projections if
|
|
|
+// `ranges::equal(range1, range2, pred, proj, proj)` would return true;
|
|
|
+// otherwise, at worst `O(N^2)`, where `N` has the value `size(range1)`.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.is.permutation#:~:text=ranges::is_permutation(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>>
|
|
|
+constexpr bool is_permutation(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::is_permutation(
|
|
|
+ ranges::begin(range1), ranges::end(range1), ranges::begin(range2),
|
|
|
+ ranges::end(range2), std::move(pred), std::move(proj1), std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.search] Search
|
|
|
+// Reference: https://wg21.link/alg.search
|
|
|
+
|
|
|
+// Returns: `i`, where `i` is the first iterator in the range
|
|
|
+// `[first1, last1 - (last2 - first2))` such that for every non-negative integer
|
|
|
+// `n` less than `last2 - first2` the condition
|
|
|
+// `bool(invoke(pred, invoke(proj1, *(i + n)), invoke(proj2, *(first2 + n))))`
|
|
|
+// is `true`.
|
|
|
+// Returns `last1` if no such iterator exists.
|
|
|
+// Note: std::ranges::search(I1 first1,...) returns a range, rather than an
|
|
|
+// iterator. For simplicitly we match std::search's return type instead.
|
|
|
+//
|
|
|
+// Complexity: At most `(last1 - first1) * (last2 - first2)` applications of the
|
|
|
+// corresponding predicate and projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.search#:~:text=ranges::search(I1
|
|
|
+template <typename ForwardIterator1,
|
|
|
+ typename ForwardIterator2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator1>,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<ForwardIterator1, Proj1>,
|
|
|
+ projected<ForwardIterator2, Proj2>>>
|
|
|
+constexpr auto search(ForwardIterator1 first1,
|
|
|
+ ForwardIterator1 last1,
|
|
|
+ ForwardIterator2 first2,
|
|
|
+ ForwardIterator2 last2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return std::search(first1, last1, first2, last2,
|
|
|
+ internal::ProjectedBinaryPredicate(pred, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: `i`, where `i` is the first iterator in the range
|
|
|
+// `[begin(range1), end(range1) - size(range2))` such that for every
|
|
|
+// non-negative integer `n` less than `size(range2)` the condition
|
|
|
+// `bool(invoke(pred, invoke(proj1, *(i + n)),
|
|
|
+// invoke(proj2, *(begin(range2) + n))))` is `true`.
|
|
|
+// Returns `end(range1)` if no such iterator exists.
|
|
|
+// Note: std::ranges::search(R1&& r1,...) returns a range, rather than an
|
|
|
+// iterator. For simplicitly we match std::search's return type instead.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range1) * size(range2)` applications of the
|
|
|
+// corresponding predicate and projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.search#:~:text=ranges::search(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = indirect_result_t<Pred&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>>
|
|
|
+constexpr auto search(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::search(ranges::begin(range1), ranges::end(range1),
|
|
|
+ ranges::begin(range2), ranges::end(range2),
|
|
|
+ std::move(pred), std::move(proj1), std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Mandates: The type `Size` is convertible to an integral type.
|
|
|
+//
|
|
|
+// Returns: `i` where `i` is the first iterator in the range
|
|
|
+// `[first, last - count)` such that for every non-negative integer `n` less
|
|
|
+// than `count`, the following condition holds:
|
|
|
+// `invoke(pred, invoke(proj, *(i + n)), value)`.
|
|
|
+// Returns `last` if no such iterator is found.
|
|
|
+// Note: std::ranges::search_n(I1 first1,...) returns a range, rather than an
|
|
|
+// iterator. For simplicitly we match std::search_n's return type instead.
|
|
|
+//
|
|
|
+// Complexity: At most `last - first` applications of the corresponding
|
|
|
+// predicate and projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.search#:~:text=ranges::search_n(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Size,
|
|
|
+ typename T,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto search_n(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Size count,
|
|
|
+ const T& value,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ // The second arg is guaranteed to be `value`, so we'll simply apply the
|
|
|
+ // identity projection.
|
|
|
+ identity value_proj;
|
|
|
+ return std::search_n(
|
|
|
+ first, last, count, value,
|
|
|
+ internal::ProjectedBinaryPredicate(pred, proj, value_proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Mandates: The type `Size` is convertible to an integral type.
|
|
|
+//
|
|
|
+// Returns: `i` where `i` is the first iterator in the range
|
|
|
+// `[begin(range), end(range) - count)` such that for every non-negative integer
|
|
|
+// `n` less than `count`, the following condition holds:
|
|
|
+// `invoke(pred, invoke(proj, *(i + n)), value)`.
|
|
|
+// Returns `end(arnge)` if no such iterator is found.
|
|
|
+// Note: std::ranges::search_n(R1&& r1,...) returns a range, rather than an
|
|
|
+// iterator. For simplicitly we match std::search_n's return type instead.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range)` applications of the corresponding predicate
|
|
|
+// and projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.search#:~:text=ranges::search_n(R
|
|
|
+template <typename Range,
|
|
|
+ typename Size,
|
|
|
+ typename T,
|
|
|
+ typename Pred = ranges::equal_to,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto search_n(Range&& range,
|
|
|
+ Size count,
|
|
|
+ const T& value,
|
|
|
+ Pred pred = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::search_n(ranges::begin(range), ranges::end(range), count,
|
|
|
+ value, std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.modifying.operations] Mutating sequence operations
|
|
|
+// Reference: https://wg21.link/alg.modifying.operations
|
|
|
+
|
|
|
+// [alg.copy] Copy
|
|
|
+// Reference: https://wg21.link/alg.copy
|
|
|
+
|
|
|
+// Let N be `last - first`.
|
|
|
+//
|
|
|
+// Preconditions: `result` is not in the range `[first, last)`.
|
|
|
+//
|
|
|
+// Effects: Copies elements in the range `[first, last)` into the range
|
|
|
+// `[result, result + N)` starting from `first` and proceeding to `last`. For
|
|
|
+// each non-negative integer `n < N` , performs `*(result + n) = *(first + n)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.copy#:~:text=ranges::copy(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto copy(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ OutputIterator result) {
|
|
|
+ return std::copy(first, last, result);
|
|
|
+}
|
|
|
+
|
|
|
+// Let N be `size(range)`.
|
|
|
+//
|
|
|
+// Preconditions: `result` is not in `range`.
|
|
|
+//
|
|
|
+// Effects: Copies elements in `range` into the range `[result, result + N)`
|
|
|
+// starting from `begin(range)` and proceeding to `end(range)`. For each
|
|
|
+// non-negative integer `n < N` , performs
|
|
|
+// *(result + n) = *(begin(range) + n)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.copy#:~:text=ranges::copy(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto copy(Range&& range, OutputIterator result) {
|
|
|
+ return ranges::copy(ranges::begin(range), ranges::end(range), result);
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `max(0, n)`.
|
|
|
+//
|
|
|
+// Mandates: The type `Size` is convertible to an integral type.
|
|
|
+//
|
|
|
+// Effects: For each non-negative integer `i < N`, performs
|
|
|
+// `*(result + i) = *(first + i)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.copy#:~:text=ranges::copy_n
|
|
|
+template <typename InputIterator,
|
|
|
+ typename Size,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto copy_n(InputIterator first, Size n, OutputIterator result) {
|
|
|
+ return std::copy_n(first, n, result);
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`, and `N` be the number
|
|
|
+// of iterators `i` in the range `[first, last)` for which the condition `E(i)`
|
|
|
+// holds.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `[first, last)` and
|
|
|
+// `[result, result + (last - first))` do not overlap.
|
|
|
+//
|
|
|
+// Effects: Copies all of the elements referred to by the iterator `i` in the
|
|
|
+// range `[first, last)` for which `E(i)` is true.
|
|
|
+//
|
|
|
+// Returns: `result + N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.copy#:~:text=ranges::copy_if(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto copy_if(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ OutputIterator result,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::copy_if(first, last, result,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`, and `N` be the number
|
|
|
+// of iterators `i` in `range` for which the condition `E(i)` holds.
|
|
|
+//
|
|
|
+// Preconditions: `range` and `[result, result + size(range))` do not overlap.
|
|
|
+//
|
|
|
+// Effects: Copies all of the elements referred to by the iterator `i` in
|
|
|
+// `range` for which `E(i)` is true.
|
|
|
+//
|
|
|
+// Returns: `result + N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of the corresponding predicate
|
|
|
+// and any projection.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.copy#:~:text=ranges::copy_if(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto copy_if(Range&& range,
|
|
|
+ OutputIterator result,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::copy_if(ranges::begin(range), ranges::end(range), result,
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `last - first`.
|
|
|
+//
|
|
|
+// Preconditions: `result` is not in the range `(first, last]`.
|
|
|
+//
|
|
|
+// Effects: Copies elements in the range `[first, last)` into the range
|
|
|
+// `[result - N, result)` starting from `last - 1` and proceeding to `first`.
|
|
|
+// For each positive integer `n ≤ N`, performs `*(result - n) = *(last - n)`.
|
|
|
+//
|
|
|
+// Returns: `result - N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.copy#:~:text=ranges::copy_backward(I1
|
|
|
+template <typename BidirectionalIterator1,
|
|
|
+ typename BidirectionalIterator2,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator1>,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator2>>
|
|
|
+constexpr auto copy_backward(BidirectionalIterator1 first,
|
|
|
+ BidirectionalIterator1 last,
|
|
|
+ BidirectionalIterator2 result) {
|
|
|
+ return std::copy_backward(first, last, result);
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `size(range)`.
|
|
|
+//
|
|
|
+// Preconditions: `result` is not in the range `(begin(range), end(range)]`.
|
|
|
+//
|
|
|
+// Effects: Copies elements in `range` into the range `[result - N, result)`
|
|
|
+// starting from `end(range) - 1` and proceeding to `begin(range)`. For each
|
|
|
+// positive integer `n ≤ N`, performs `*(result - n) = *(end(range) - n)`.
|
|
|
+//
|
|
|
+// Returns: `result - N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.copy#:~:text=ranges::copy_backward(R
|
|
|
+template <typename Range,
|
|
|
+ typename BidirectionalIterator,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator>>
|
|
|
+constexpr auto copy_backward(Range&& range, BidirectionalIterator result) {
|
|
|
+ return ranges::copy_backward(ranges::begin(range), ranges::end(range),
|
|
|
+ result);
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.move] Move
|
|
|
+// Reference: https://wg21.link/alg.move
|
|
|
+
|
|
|
+// Let `E(n)` be `std::move(*(first + n))`.
|
|
|
+//
|
|
|
+// Let `N` be `last - first`.
|
|
|
+//
|
|
|
+// Preconditions: `result` is not in the range `[first, last)`.
|
|
|
+//
|
|
|
+// Effects: Moves elements in the range `[first, last)` into the range `[result,
|
|
|
+// result + N)` starting from `first` and proceeding to `last`. For each
|
|
|
+// non-negative integer `n < N`, performs `*(result + n) = E(n)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.move#:~:text=ranges::move(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto move(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ OutputIterator result) {
|
|
|
+ return std::move(first, last, result);
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(n)` be `std::move(*(begin(range) + n))`.
|
|
|
+//
|
|
|
+// Let `N` be `size(range)`.
|
|
|
+//
|
|
|
+// Preconditions: `result` is not in `range`.
|
|
|
+//
|
|
|
+// Effects: Moves elements in `range` into the range `[result, result + N)`
|
|
|
+// starting from `begin(range)` and proceeding to `end(range)`. For each
|
|
|
+// non-negative integer `n < N`, performs `*(result + n) = E(n)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.move#:~:text=ranges::move(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto move(Range&& range, OutputIterator result) {
|
|
|
+ return ranges::move(ranges::begin(range), ranges::end(range), result);
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(n)` be `std::move(*(last - n))`.
|
|
|
+//
|
|
|
+// Let `N` be `last - first`.
|
|
|
+//
|
|
|
+// Preconditions: `result` is not in the range `(first, last]`.
|
|
|
+//
|
|
|
+// Effects: Moves elements in the range `[first, last)` into the range
|
|
|
+// `[result - N, result)` starting from `last - 1` and proceeding to `first`.
|
|
|
+// For each positive integer `n ≤ N`, performs `*(result - n) = E(n)`.
|
|
|
+//
|
|
|
+// Returns: `result - N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.move#:~:text=ranges::move_backward(I1
|
|
|
+template <typename BidirectionalIterator1,
|
|
|
+ typename BidirectionalIterator2,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator1>,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator2>>
|
|
|
+constexpr auto move_backward(BidirectionalIterator1 first,
|
|
|
+ BidirectionalIterator1 last,
|
|
|
+ BidirectionalIterator2 result) {
|
|
|
+ return std::move_backward(first, last, result);
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(n)` be `std::move(*(end(range) - n))`.
|
|
|
+//
|
|
|
+// Let `N` be `size(range)`.
|
|
|
+//
|
|
|
+// Preconditions: `result` is not in the range `(begin(range), end(range)]`.
|
|
|
+//
|
|
|
+// Effects: Moves elements in `range` into the range `[result - N, result)`
|
|
|
+// starting from `end(range) - 1` and proceeding to `begin(range)`. For each
|
|
|
+// positive integer `n ≤ N`, performs `*(result - n) = E(n)`.
|
|
|
+//
|
|
|
+// Returns: `result - N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.move#:~:text=ranges::move_backward(R
|
|
|
+template <typename Range,
|
|
|
+ typename BidirectionalIterator,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator>>
|
|
|
+constexpr auto move_backward(Range&& range, BidirectionalIterator result) {
|
|
|
+ return ranges::move_backward(ranges::begin(range), ranges::end(range),
|
|
|
+ result);
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.swap] Swap
|
|
|
+// Reference: https://wg21.link/alg.swap
|
|
|
+
|
|
|
+// Let `M` be `min(last1 - first1, last2 - first2)`.
|
|
|
+//
|
|
|
+// Preconditions: The two ranges `[first1, last1)` and `[first2, last2)` do not
|
|
|
+// overlap. `*(first1 + n)` is swappable with `*(first2 + n)`.
|
|
|
+//
|
|
|
+// Effects: For each non-negative integer `n < M` performs
|
|
|
+// `swap(*(first1 + n), *(first2 + n))`
|
|
|
+//
|
|
|
+// Returns: `first2 + M`
|
|
|
+//
|
|
|
+// Complexity: Exactly `M` swaps.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.swap#:~:text=ranges::swap_ranges(I1
|
|
|
+template <typename ForwardIterator1,
|
|
|
+ typename ForwardIterator2,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator1>,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator2>>
|
|
|
+constexpr auto swap_ranges(ForwardIterator1 first1,
|
|
|
+ ForwardIterator1 last1,
|
|
|
+ ForwardIterator2 first2,
|
|
|
+ ForwardIterator2 last2) {
|
|
|
+ // std::swap_ranges does not have a `last2` overload. Thus we need to
|
|
|
+ // adjust `last1` to ensure to not read past `last2`.
|
|
|
+ last1 = std::next(first1, std::min(std::distance(first1, last1),
|
|
|
+ std::distance(first2, last2)));
|
|
|
+ return std::swap_ranges(first1, last1, first2);
|
|
|
+}
|
|
|
+
|
|
|
+// Let `M` be `min(size(range1), size(range2))`.
|
|
|
+//
|
|
|
+// Preconditions: The two ranges `range1` and `range2` do not overlap.
|
|
|
+// `*(begin(range1) + n)` is swappable with `*(begin(range2) + n)`.
|
|
|
+//
|
|
|
+// Effects: For each non-negative integer `n < M` performs
|
|
|
+// `swap(*(begin(range1) + n), *(begin(range2) + n))`
|
|
|
+//
|
|
|
+// Returns: `begin(range2) + M`
|
|
|
+//
|
|
|
+// Complexity: Exactly `M` swaps.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.swap#:~:text=ranges::swap_ranges(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>>
|
|
|
+constexpr auto swap_ranges(Range1&& range1, Range2&& range2) {
|
|
|
+ return ranges::swap_ranges(ranges::begin(range1), ranges::end(range1),
|
|
|
+ ranges::begin(range2), ranges::end(range2));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.transform] Transform
|
|
|
+// Reference: https://wg21.link/alg.transform
|
|
|
+
|
|
|
+// Let `N` be `last1 - first1`,
|
|
|
+// `E(i)` be `invoke(op, invoke(proj, *(first1 + (i - result))))`.
|
|
|
+//
|
|
|
+// Preconditions: `op` does not invalidate iterators or subranges, nor modify
|
|
|
+// elements in the ranges `[first1, first1 + N]`, and `[result, result + N]`.
|
|
|
+//
|
|
|
+// Effects: Assigns through every iterator `i` in the range
|
|
|
+// `[result, result + N)` a new corresponding value equal to `E(i)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` applications of `op` and any projections.
|
|
|
+//
|
|
|
+// Remarks: result may be equal to `first1`.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.transform#:~:text=ranges::transform(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename UnaryOperation,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<UnaryOperation&,
|
|
|
+ projected<InputIterator, Proj>>>
|
|
|
+constexpr auto transform(InputIterator first1,
|
|
|
+ InputIterator last1,
|
|
|
+ OutputIterator result,
|
|
|
+ UnaryOperation op,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::transform(first1, last1, result, [&op, &proj](auto&& arg) {
|
|
|
+ return base::invoke(op,
|
|
|
+ base::invoke(proj, std::forward<decltype(arg)>(arg)));
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `size(range)`,
|
|
|
+// `E(i)` be `invoke(op, invoke(proj, *(begin(range) + (i - result))))`.
|
|
|
+//
|
|
|
+// Preconditions: `op` does not invalidate iterators or subranges, nor modify
|
|
|
+// elements in the ranges `[begin(range), end(range)]`, and
|
|
|
+// `[result, result + N]`.
|
|
|
+//
|
|
|
+// Effects: Assigns through every iterator `i` in the range
|
|
|
+// `[result, result + N)` a new corresponding value equal to `E(i)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` applications of `op` and any projections.
|
|
|
+//
|
|
|
+// Remarks: result may be equal to `begin(range)`.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.transform#:~:text=ranges::transform(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename UnaryOperation,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<UnaryOperation&,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto transform(Range&& range,
|
|
|
+ OutputIterator result,
|
|
|
+ UnaryOperation op,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::transform(ranges::begin(range), ranges::end(range), result,
|
|
|
+ std::move(op), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let:
|
|
|
+// `N` be `min(last1 - first1, last2 - first2)`,
|
|
|
+// `E(i)` be `invoke(binary_op, invoke(proj1, *(first1 + (i - result))),
|
|
|
+// invoke(proj2, *(first2 + (i - result))))`.
|
|
|
+//
|
|
|
+// Preconditions: `binary_op` does not invalidate iterators or subranges, nor
|
|
|
+// modify elements in the ranges `[first1, first1 + N]`, `[first2, first2 + N]`,
|
|
|
+// and `[result, result + N]`.
|
|
|
+//
|
|
|
+// Effects: Assigns through every iterator `i` in the range
|
|
|
+// `[result, result + N)` a new corresponding value equal to `E(i)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` applications of `binary_op`, and any projections.
|
|
|
+//
|
|
|
+// Remarks: `result` may be equal to `first1` or `first2`.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.transform#:~:text=ranges::transform(I1
|
|
|
+template <typename ForwardIterator1,
|
|
|
+ typename ForwardIterator2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename BinaryOperation,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator1>,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<BinaryOperation&,
|
|
|
+ projected<ForwardIterator1, Proj1>,
|
|
|
+ projected<ForwardIterator2, Proj2>>>
|
|
|
+constexpr auto transform(ForwardIterator1 first1,
|
|
|
+ ForwardIterator1 last1,
|
|
|
+ ForwardIterator2 first2,
|
|
|
+ ForwardIterator2 last2,
|
|
|
+ OutputIterator result,
|
|
|
+ BinaryOperation binary_op,
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ // std::transform does not have a `last2` overload. Thus we need to adjust
|
|
|
+ // `last1` to ensure to not read past `last2`.
|
|
|
+ last1 = std::next(first1, std::min(std::distance(first1, last1),
|
|
|
+ std::distance(first2, last2)));
|
|
|
+ return std::transform(
|
|
|
+ first1, last1, first2, result,
|
|
|
+ [&binary_op, &proj1, &proj2](auto&& lhs, auto&& rhs) {
|
|
|
+ return base::invoke(
|
|
|
+ binary_op, base::invoke(proj1, std::forward<decltype(lhs)>(lhs)),
|
|
|
+ base::invoke(proj2, std::forward<decltype(rhs)>(rhs)));
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// Let:
|
|
|
+// `N` be `min(size(range1), size(range2)`,
|
|
|
+// `E(i)` be `invoke(binary_op, invoke(proj1, *(begin(range1) + (i - result))),
|
|
|
+// invoke(proj2, *(begin(range2) + (i - result))))`
|
|
|
+//
|
|
|
+// Preconditions: `binary_op` does not invalidate iterators or subranges, nor
|
|
|
+// modify elements in the ranges `[begin(range1), end(range1)]`,
|
|
|
+// `[begin(range2), end(range2)]`, and `[result, result + N]`.
|
|
|
+//
|
|
|
+// Effects: Assigns through every iterator `i` in the range
|
|
|
+// `[result, result + N)` a new corresponding value equal to `E(i)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` applications of `binary_op`, and any projections.
|
|
|
+//
|
|
|
+// Remarks: `result` may be equal to `begin(range1)` or `begin(range2)`.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.transform#:~:text=ranges::transform(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename BinaryOperation,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<BinaryOperation&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>>
|
|
|
+constexpr auto transform(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ OutputIterator result,
|
|
|
+ BinaryOperation binary_op,
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::transform(ranges::begin(range1), ranges::end(range1),
|
|
|
+ ranges::begin(range2), ranges::end(range2), result,
|
|
|
+ std::move(binary_op), std::move(proj1),
|
|
|
+ std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.replace] Replace
|
|
|
+// Reference: https://wg21.link/alg.replace
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(proj, *i) == old_value)`.
|
|
|
+//
|
|
|
+// Mandates: `new_value` is writable to `first`.
|
|
|
+//
|
|
|
+// Effects: Substitutes elements referred by the iterator `i` in the range
|
|
|
+// `[first, last)` with `new_value`, when `E(i)` is true.
|
|
|
+//
|
|
|
+// Returns: `last`
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto replace(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ const T& old_value,
|
|
|
+ const T& new_value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ // Note: In order to be able to apply `proj` to each element in [first, last)
|
|
|
+ // we are dispatching to std::replace_if instead of std::replace.
|
|
|
+ std::replace_if(
|
|
|
+ first, last,
|
|
|
+ [&proj, &old_value](auto&& lhs) {
|
|
|
+ return base::invoke(proj, std::forward<decltype(lhs)>(lhs)) ==
|
|
|
+ old_value;
|
|
|
+ },
|
|
|
+ new_value);
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(proj, *i) == old_value)`.
|
|
|
+//
|
|
|
+// Mandates: `new_value` is writable to `begin(range)`.
|
|
|
+//
|
|
|
+// Effects: Substitutes elements referred by the iterator `i` in `range` with
|
|
|
+// `new_value`, when `E(i)` is true.
|
|
|
+//
|
|
|
+// Returns: `end(range)`
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of the corresponding predicate
|
|
|
+// and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace(R
|
|
|
+template <typename Range,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto replace(Range&& range,
|
|
|
+ const T& old_value,
|
|
|
+ const T& new_value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::replace(ranges::begin(range), ranges::end(range), old_value,
|
|
|
+ new_value, std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Mandates: `new_value` is writable to `first`.
|
|
|
+//
|
|
|
+// Effects: Substitutes elements referred by the iterator `i` in the range
|
|
|
+// `[first, last)` with `new_value`, when `E(i)` is true.
|
|
|
+//
|
|
|
+// Returns: `last`
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_if(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Predicate,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto replace_if(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Predicate pred,
|
|
|
+ const T& new_value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ std::replace_if(first, last, internal::ProjectedUnaryPredicate(pred, proj),
|
|
|
+ new_value);
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Mandates: `new_value` is writable to `begin(range)`.
|
|
|
+//
|
|
|
+// Effects: Substitutes elements referred by the iterator `i` in `range` with
|
|
|
+// `new_value`, when `E(i)` is true.
|
|
|
+//
|
|
|
+// Returns: `end(range)`
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of the corresponding predicate
|
|
|
+// and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_if(R
|
|
|
+template <typename Range,
|
|
|
+ typename Predicate,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto replace_if(Range&& range,
|
|
|
+ Predicate pred,
|
|
|
+ const T& new_value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::replace_if(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), new_value, std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(proj, *(first + (i - result))) == old_value)`.
|
|
|
+//
|
|
|
+// Mandates: The results of the expressions `*first` and `new_value` are
|
|
|
+// writable to `result`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `[first, last)` and `[result, result + (last -
|
|
|
+// first))` do not overlap.
|
|
|
+//
|
|
|
+// Effects: Assigns through every iterator `i` in the range `[result, result +
|
|
|
+// (last - first))` a new corresponding value, `new_value` if `E(i)` is true, or
|
|
|
+// `*(first + (i - result))` otherwise.
|
|
|
+//
|
|
|
+// Returns: `result + (last - first)`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto replace_copy(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ OutputIterator result,
|
|
|
+ const T& old_value,
|
|
|
+ const T& new_value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ // Note: In order to be able to apply `proj` to each element in [first, last)
|
|
|
+ // we are dispatching to std::replace_copy_if instead of std::replace_copy.
|
|
|
+ std::replace_copy_if(
|
|
|
+ first, last, result,
|
|
|
+ [&proj, &old_value](auto&& lhs) {
|
|
|
+ return base::invoke(proj, std::forward<decltype(lhs)>(lhs)) ==
|
|
|
+ old_value;
|
|
|
+ },
|
|
|
+ new_value);
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be
|
|
|
+// `bool(invoke(proj, *(begin(range) + (i - result))) == old_value)`.
|
|
|
+//
|
|
|
+// Mandates: The results of the expressions `*begin(range)` and `new_value` are
|
|
|
+// writable to `result`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `range` and `[result, result + size(range))` do not
|
|
|
+// overlap.
|
|
|
+//
|
|
|
+// Effects: Assigns through every iterator `i` in the range `[result, result +
|
|
|
+// size(range))` a new corresponding value, `new_value` if `E(i)` is true, or
|
|
|
+// `*(begin(range) + (i - result))` otherwise.
|
|
|
+//
|
|
|
+// Returns: `result + size(range)`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto replace_copy(Range&& range,
|
|
|
+ OutputIterator result,
|
|
|
+ const T& old_value,
|
|
|
+ const T& new_value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::replace_copy(ranges::begin(range), ranges::end(range), result,
|
|
|
+ old_value, new_value, std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *(first + (i - result)))))`.
|
|
|
+//
|
|
|
+// Mandates: The results of the expressions `*first` and `new_value` are
|
|
|
+// writable to `result`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `[first, last)` and `[result, result + (last -
|
|
|
+// first))` do not overlap.
|
|
|
+//
|
|
|
+// Effects: Assigns through every iterator `i` in the range `[result, result +
|
|
|
+// (last - first))` a new corresponding value, `new_value` if `E(i)` is true, or
|
|
|
+// `*(first + (i - result))` otherwise.
|
|
|
+//
|
|
|
+// Returns: `result + (last - first)`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy_if(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Predicate,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto replace_copy_if(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ OutputIterator result,
|
|
|
+ Predicate pred,
|
|
|
+ const T& new_value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::replace_copy_if(first, last, result,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj),
|
|
|
+ new_value);
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be
|
|
|
+// `bool(invoke(pred, invoke(proj, *(begin(range) + (i - result)))))`.
|
|
|
+//
|
|
|
+// Mandates: The results of the expressions `*begin(range)` and `new_value` are
|
|
|
+// writable to `result`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `range` and `[result, result + size(range))` do not
|
|
|
+// overlap.
|
|
|
+//
|
|
|
+// Effects: Assigns through every iterator `i` in the range `[result, result +
|
|
|
+// size(range))` a new corresponding value, `new_value` if `E(i)` is true, or
|
|
|
+// `*(begin(range) + (i - result))` otherwise.
|
|
|
+//
|
|
|
+// Returns: `result + size(range)`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy_if(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Predicate,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto replace_copy_if(Range&& range,
|
|
|
+ OutputIterator result,
|
|
|
+ Predicate pred,
|
|
|
+ const T& new_value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::replace_copy_if(ranges::begin(range), ranges::end(range),
|
|
|
+ result, pred, new_value, std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.fill] Fill
|
|
|
+// Reference: https://wg21.link/alg.fill
|
|
|
+
|
|
|
+// Let `N` be `last - first`.
|
|
|
+//
|
|
|
+// Mandates: The expression `value` is writable to the output iterator.
|
|
|
+//
|
|
|
+// Effects: Assigns `value` through all the iterators in the range
|
|
|
+// `[first, last)`.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.fill#:~:text=ranges::fill(O
|
|
|
+template <typename OutputIterator,
|
|
|
+ typename T,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto fill(OutputIterator first, OutputIterator last, const T& value) {
|
|
|
+ std::fill(first, last, value);
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `size(range)`.
|
|
|
+//
|
|
|
+// Mandates: The expression `value` is writable to the output iterator.
|
|
|
+//
|
|
|
+// Effects: Assigns `value` through all the iterators in `range`.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.fill#:~:text=ranges::fill(R
|
|
|
+template <typename Range,
|
|
|
+ typename T,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto fill(Range&& range, const T& value) {
|
|
|
+ return ranges::fill(ranges::begin(range), ranges::end(range), value);
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `max(0, n)`.
|
|
|
+//
|
|
|
+// Mandates: The expression `value` is writable to the output iterator.
|
|
|
+// The type `Size` is convertible to an integral type.
|
|
|
+//
|
|
|
+// Effects: Assigns `value` through all the iterators in `[first, first + N)`.
|
|
|
+//
|
|
|
+// Returns: `first + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.fill#:~:text=ranges::fill_n(O
|
|
|
+template <typename OutputIterator,
|
|
|
+ typename Size,
|
|
|
+ typename T,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto fill_n(OutputIterator first, Size n, const T& value) {
|
|
|
+ return std::fill_n(first, n, value);
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.generate] Generate
|
|
|
+// Reference: https://wg21.link/alg.generate
|
|
|
+
|
|
|
+// Let `N` be `last - first`.
|
|
|
+//
|
|
|
+// Effects: Assigns the result of successive evaluations of gen() through each
|
|
|
+// iterator in the range `[first, last)`.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` evaluations of `gen()` and assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.generate#:~:text=ranges::generate(O
|
|
|
+template <typename OutputIterator,
|
|
|
+ typename Generator,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto generate(OutputIterator first,
|
|
|
+ OutputIterator last,
|
|
|
+ Generator gen) {
|
|
|
+ std::generate(first, last, std::move(gen));
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `size(range)`.
|
|
|
+//
|
|
|
+// Effects: Assigns the result of successive evaluations of gen() through each
|
|
|
+// iterator in `range`.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` evaluations of `gen()` and assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.generate#:~:text=ranges::generate(R
|
|
|
+template <typename Range,
|
|
|
+ typename Generator,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto generate(Range&& range, Generator gen) {
|
|
|
+ return ranges::generate(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(gen));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `max(0, n)`.
|
|
|
+//
|
|
|
+// Mandates: `Size` is convertible to an integral type.
|
|
|
+//
|
|
|
+// Effects: Assigns the result of successive evaluations of gen() through each
|
|
|
+// iterator in the range `[first, first + N)`.
|
|
|
+//
|
|
|
+// Returns: `first + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` evaluations of `gen()` and assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.generate#:~:text=ranges::generate_n(O
|
|
|
+template <typename OutputIterator,
|
|
|
+ typename Size,
|
|
|
+ typename Generator,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto generate_n(OutputIterator first, Size n, Generator gen) {
|
|
|
+ return std::generate_n(first, n, std::move(gen));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.remove] Remove
|
|
|
+// Reference: https://wg21.link/alg.remove
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(proj, *i) == value)`.
|
|
|
+//
|
|
|
+// Effects: Eliminates all the elements referred to by iterator `i` in the range
|
|
|
+// `[first, last)` for which `E(i)` holds.
|
|
|
+//
|
|
|
+// Returns: The end of the resulting range.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.remove#:~:text=ranges::remove(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto remove(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ const T& value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ // Note: In order to be able to apply `proj` to each element in [first, last)
|
|
|
+ // we are dispatching to std::remove_if instead of std::remove.
|
|
|
+ return std::remove_if(first, last, [&proj, &value](auto&& lhs) {
|
|
|
+ return base::invoke(proj, std::forward<decltype(lhs)>(lhs)) == value;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(proj, *i) == value)`.
|
|
|
+//
|
|
|
+// Effects: Eliminates all the elements referred to by iterator `i` in `range`
|
|
|
+// for which `E(i)` holds.
|
|
|
+//
|
|
|
+// Returns: The end of the resulting range.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of the corresponding predicate
|
|
|
+// and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.remove#:~:text=ranges::remove(R
|
|
|
+template <typename Range,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto remove(Range&& range, const T& value, Proj proj = {}) {
|
|
|
+ return ranges::remove(ranges::begin(range), ranges::end(range), value,
|
|
|
+ std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Effects: Eliminates all the elements referred to by iterator `i` in the range
|
|
|
+// `[first, last)` for which `E(i)` holds.
|
|
|
+//
|
|
|
+// Returns: The end of the resulting range.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_if(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Predicate,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto remove_if(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Predicate pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::remove_if(first, last,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Effects: Eliminates all the elements referred to by iterator `i` in `range`.
|
|
|
+//
|
|
|
+// Returns: The end of the resulting range.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of the corresponding predicate
|
|
|
+// and any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_if(R
|
|
|
+template <typename Range,
|
|
|
+ typename Predicate,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto remove_if(Range&& range, Predicate pred, Proj proj = {}) {
|
|
|
+ return ranges::remove_if(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(proj, *i) == value)`.
|
|
|
+//
|
|
|
+// Let `N` be the number of elements in `[first, last)` for which `E(i)` is
|
|
|
+// false.
|
|
|
+//
|
|
|
+// Mandates: `*first` is writable to `result`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `[first, last)` and `[result, result + (last -
|
|
|
+// first))` do not overlap.
|
|
|
+//
|
|
|
+// Effects: Copies all the elements referred to by the iterator `i` in the range
|
|
|
+// `[first, last)` for which `E(i)` is false.
|
|
|
+//
|
|
|
+// Returns: `result + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_copy(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto remove_copy(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ OutputIterator result,
|
|
|
+ const T& value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ // Note: In order to be able to apply `proj` to each element in [first, last)
|
|
|
+ // we are dispatching to std::remove_copy_if instead of std::remove_copy.
|
|
|
+ return std::remove_copy_if(first, last, result, [&proj, &value](auto&& lhs) {
|
|
|
+ return base::invoke(proj, std::forward<decltype(lhs)>(lhs)) == value;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(proj, *i) == value)`.
|
|
|
+//
|
|
|
+// Let `N` be the number of elements in `range` for which `E(i)` is false.
|
|
|
+//
|
|
|
+// Mandates: `*begin(range)` is writable to `result`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `range` and `[result, result + size(range))` do not
|
|
|
+// overlap.
|
|
|
+//
|
|
|
+// Effects: Copies all the elements referred to by the iterator `i` in `range`
|
|
|
+// for which `E(i)` is false.
|
|
|
+//
|
|
|
+// Returns: `result + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_copy(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename T,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto remove_copy(Range&& range,
|
|
|
+ OutputIterator result,
|
|
|
+ const T& value,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::remove_copy(ranges::begin(range), ranges::end(range), result,
|
|
|
+ value, std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Let `N` be the number of elements in `[first, last)` for which `E(i)` is
|
|
|
+// false.
|
|
|
+//
|
|
|
+// Mandates: `*first` is writable to `result`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `[first, last)` and `[result, result + (last -
|
|
|
+// first))` do not overlap.
|
|
|
+//
|
|
|
+// Effects: Copies all the elements referred to by the iterator `i` in the range
|
|
|
+// `[first, last)` for which `E(i)` is false.
|
|
|
+//
|
|
|
+// Returns: `result + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_copy_if(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto remove_copy_if(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ OutputIterator result,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::remove_copy_if(first, last, result,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Let `N` be the number of elements in `range` for which `E(i)` is false.
|
|
|
+//
|
|
|
+// Mandates: `*begin(range)` is writable to `result`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `range` and `[result, result + size(range))` do not
|
|
|
+// overlap.
|
|
|
+//
|
|
|
+// Effects: Copies all the elements referred to by the iterator `i` in `range`
|
|
|
+// for which `E(i)` is false.
|
|
|
+//
|
|
|
+// Returns: `result + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of the corresponding
|
|
|
+// predicate and any projection.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.remove#:~:text=ranges::remove_copy(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto remove_copy_if(Range&& range,
|
|
|
+ OutputIterator result,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::remove_copy_if(ranges::begin(range), ranges::end(range),
|
|
|
+ result, std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.unique] Unique
|
|
|
+// Reference: https://wg21.link/alg.unique
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(comp, invoke(proj, *(i - 1)), invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Effects: For a nonempty range, eliminates all but the first element from
|
|
|
+// every consecutive group of equivalent elements referred to by the iterator
|
|
|
+// `i` in the range `[first + 1, last)` for which `E(i)` is true.
|
|
|
+//
|
|
|
+// Returns: The end of the resulting range.
|
|
|
+//
|
|
|
+// Complexity: For nonempty ranges, exactly `(last - first) - 1` applications of
|
|
|
+// the corresponding predicate and no more than twice as many applications of
|
|
|
+// any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.unique#:~:text=ranges::unique(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Comp = ranges::equal_to,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<ForwardIterator, Proj>,
|
|
|
+ projected<ForwardIterator, Proj>>>
|
|
|
+constexpr auto unique(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::unique(first, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(comp, invoke(proj, *(i - 1)), invoke(proj, *i)))`.
|
|
|
+//
|
|
|
+// Effects: For a nonempty range, eliminates all but the first element from
|
|
|
+// every consecutive group of equivalent elements referred to by the iterator
|
|
|
+// `i` in the range `[begin(range) + 1, end(range))` for which `E(i)` is true.
|
|
|
+//
|
|
|
+// Returns: The end of the resulting range.
|
|
|
+//
|
|
|
+// Complexity: For nonempty ranges, exactly `size(range) - 1` applications of
|
|
|
+// the corresponding predicate and no more than twice as many applications of
|
|
|
+// any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.unique#:~:text=ranges::unique(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::equal_to,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto unique(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::unique(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(comp, invoke(proj, *i), invoke(proj, *(i - 1))))`.
|
|
|
+//
|
|
|
+// Mandates: `*first` is writable to `result`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `[first, last)` and
|
|
|
+// `[result, result + (last - first))` do not overlap.
|
|
|
+//
|
|
|
+// Effects: Copies only the first element from every consecutive group of equal
|
|
|
+// elements referred to by the iterator `i` in the range `[first, last)` for
|
|
|
+// which `E(i)` holds.
|
|
|
+//
|
|
|
+// Returns: `result + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first - 1` applications of the corresponding
|
|
|
+// predicate and no more than twice as many applications of any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.unique#:~:text=ranges::unique_copy(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::equal_to,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto unique_copy(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::unique_copy(first, last, result,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(i)` be `bool(invoke(comp, invoke(proj, *i), invoke(proj, *(i - 1))))`.
|
|
|
+//
|
|
|
+// Mandates: `*begin(range)` is writable to `result`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `range` and `[result, result + size(range))` do not
|
|
|
+// overlap.
|
|
|
+//
|
|
|
+// Effects: Copies only the first element from every consecutive group of equal
|
|
|
+// elements referred to by the iterator `i` in `range` for which `E(i)` holds.
|
|
|
+//
|
|
|
+// Returns: `result + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range) - 1` applications of the corresponding
|
|
|
+// predicate and no more than twice as many applications of any projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.unique#:~:text=ranges::unique_copy(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::equal_to,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto unique_copy(Range&& range,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::unique_copy(ranges::begin(range), ranges::end(range), result,
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.reverse] Reverse
|
|
|
+// Reference: https://wg21.link/alg.reverse
|
|
|
+
|
|
|
+// Effects: For each non-negative integer `i < (last - first) / 2`, applies
|
|
|
+// `std::iter_swap` to all pairs of iterators `first + i, (last - i) - 1`.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `(last - first)/2` swaps.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.reverse#:~:text=ranges::reverse(I
|
|
|
+template <typename BidirectionalIterator,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator>>
|
|
|
+constexpr auto reverse(BidirectionalIterator first,
|
|
|
+ BidirectionalIterator last) {
|
|
|
+ std::reverse(first, last);
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Effects: For each non-negative integer `i < size(range) / 2`, applies
|
|
|
+// `std::iter_swap` to all pairs of iterators
|
|
|
+// `begin(range) + i, (end(range) - i) - 1`.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)/2` swaps.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.reverse#:~:text=ranges::reverse(R
|
|
|
+template <typename Range, typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto reverse(Range&& range) {
|
|
|
+ return ranges::reverse(ranges::begin(range), ranges::end(range));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `last - first`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `[first, last)` and `[result, result + N)` do not
|
|
|
+// overlap.
|
|
|
+//
|
|
|
+// Effects: Copies the range `[first, last)` to the range `[result, result + N)`
|
|
|
+// such that for every non-negative integer `i < N` the following assignment
|
|
|
+// takes place: `*(result + N - 1 - i) = *(first + i)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.reverse#:~:text=ranges::reverse_copy(I
|
|
|
+template <typename BidirectionalIterator,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto reverse_copy(BidirectionalIterator first,
|
|
|
+ BidirectionalIterator last,
|
|
|
+ OutputIterator result) {
|
|
|
+ return std::reverse_copy(first, last, result);
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `size(range)`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `range` and `[result, result + N)` do not
|
|
|
+// overlap.
|
|
|
+//
|
|
|
+// Effects: Copies `range` to the range `[result, result + N)` such that for
|
|
|
+// every non-negative integer `i < N` the following assignment takes place:
|
|
|
+// `*(result + N - 1 - i) = *(begin(range) + i)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.reverse#:~:text=ranges::reverse_copy(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto reverse_copy(Range&& range, OutputIterator result) {
|
|
|
+ return ranges::reverse_copy(ranges::begin(range), ranges::end(range), result);
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.rotate] Rotate
|
|
|
+// Reference: https://wg21.link/alg.rotate
|
|
|
+
|
|
|
+// Preconditions: `[first, middle)` and `[middle, last)` are valid ranges.
|
|
|
+//
|
|
|
+// Effects: For each non-negative integer `i < (last - first)`, places the
|
|
|
+// element from the position `first + i` into position
|
|
|
+// `first + (i + (last - middle)) % (last - first)`.
|
|
|
+//
|
|
|
+// Returns: `first + (last - middle)`.
|
|
|
+//
|
|
|
+// Complexity: At most `last - first` swaps.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.rotate#:~:text=ranges::rotate(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto rotate(ForwardIterator first,
|
|
|
+ ForwardIterator middle,
|
|
|
+ ForwardIterator last) {
|
|
|
+ return std::rotate(first, middle, last);
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `[begin(range), middle)` and `[middle, end(range))` are valid
|
|
|
+// ranges.
|
|
|
+//
|
|
|
+// Effects: For each non-negative integer `i < size(range)`, places the element
|
|
|
+// from the position `begin(range) + i` into position
|
|
|
+// `begin(range) + (i + (end(range) - middle)) % size(range)`.
|
|
|
+//
|
|
|
+// Returns: `begin(range) + (end(range) - middle)`.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range)` swaps.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.rotate#:~:text=ranges::rotate(R
|
|
|
+template <typename Range, typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto rotate(Range&& range, iterator_t<Range> middle) {
|
|
|
+ return ranges::rotate(ranges::begin(range), middle, ranges::end(range));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `last - first`.
|
|
|
+//
|
|
|
+// Preconditions: `[first, middle)` and `[middle, last)` are valid ranges. The
|
|
|
+// ranges `[first, last)` and `[result, result + N)` do not overlap.
|
|
|
+//
|
|
|
+// Effects: Copies the range `[first, last)` to the range `[result, result + N)`
|
|
|
+// such that for each non-negative integer `i < N` the following assignment
|
|
|
+// takes place: `*(result + i) = *(first + (i + (middle - first)) % N)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.rotate#:~:text=ranges::rotate_copy(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto rotate_copy(ForwardIterator first,
|
|
|
+ ForwardIterator middle,
|
|
|
+ ForwardIterator last,
|
|
|
+ OutputIterator result) {
|
|
|
+ return std::rotate_copy(first, middle, last, result);
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `size(range)`.
|
|
|
+//
|
|
|
+// Preconditions: `[begin(range), middle)` and `[middle, end(range))` are valid
|
|
|
+// ranges. The ranges `range` and `[result, result + N)` do not overlap.
|
|
|
+//
|
|
|
+// Effects: Copies `range` to the range `[result, result + N)` such that for
|
|
|
+// each non-negative integer `i < N` the following assignment takes place:
|
|
|
+// `*(result + i) = *(begin(range) + (i + (middle - begin(range))) % N)`.
|
|
|
+//
|
|
|
+// Returns: `result + N`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `N` assignments.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.rotate#:~:text=ranges::rotate_copy(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>>
|
|
|
+constexpr auto rotate_copy(Range&& range,
|
|
|
+ iterator_t<Range> middle,
|
|
|
+ OutputIterator result) {
|
|
|
+ return ranges::rotate_copy(ranges::begin(range), middle, ranges::end(range),
|
|
|
+ result);
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.random.sample] Sample
|
|
|
+// Reference: https://wg21.link/alg.random.sample
|
|
|
+
|
|
|
+// Currently not implemented due to lack of std::sample in C++14.
|
|
|
+// TODO(crbug.com/1071094): Consider implementing a hand-rolled version.
|
|
|
+
|
|
|
+// [alg.random.shuffle] Shuffle
|
|
|
+// Reference: https://wg21.link/alg.random.shuffle
|
|
|
+
|
|
|
+// Preconditions: The type `std::remove_reference_t<UniformRandomBitGenerator>`
|
|
|
+// meets the uniform random bit generator requirements.
|
|
|
+//
|
|
|
+// Effects: Permutes the elements in the range `[first, last)` such that each
|
|
|
+// possible permutation of those elements has equal probability of appearance.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `(last - first) - 1` swaps.
|
|
|
+//
|
|
|
+// Remarks: To the extent that the implementation of this function makes use of
|
|
|
+// random numbers, the object referenced by g shall serve as the
|
|
|
+// implementation's source of randomness.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.random.shuffle#:~:text=ranges::shuffle(I
|
|
|
+template <typename RandomAccessIterator,
|
|
|
+ typename UniformRandomBitGenerator,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>>
|
|
|
+constexpr auto shuffle(RandomAccessIterator first,
|
|
|
+ RandomAccessIterator last,
|
|
|
+ UniformRandomBitGenerator&& g) {
|
|
|
+ std::shuffle(first, last, std::forward<UniformRandomBitGenerator>(g));
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: The type `std::remove_reference_t<UniformRandomBitGenerator>`
|
|
|
+// meets the uniform random bit generator requirements.
|
|
|
+//
|
|
|
+// Effects: Permutes the elements in `range` such that each possible permutation
|
|
|
+// of those elements has equal probability of appearance.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range) - 1` swaps.
|
|
|
+//
|
|
|
+// Remarks: To the extent that the implementation of this function makes use of
|
|
|
+// random numbers, the object referenced by g shall serve as the
|
|
|
+// implementation's source of randomness.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.random.shuffle#:~:text=ranges::shuffle(R
|
|
|
+template <typename Range,
|
|
|
+ typename UniformRandomBitGenerator,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto shuffle(Range&& range, UniformRandomBitGenerator&& g) {
|
|
|
+ return ranges::shuffle(ranges::begin(range), ranges::end(range),
|
|
|
+ std::forward<UniformRandomBitGenerator>(g));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.nonmodifying] Sorting and related operations
|
|
|
+// Reference: https://wg21.link/alg.sorting
|
|
|
+
|
|
|
+// [alg.sort] Sorting
|
|
|
+// Reference: https://wg21.link/alg.sort
|
|
|
+
|
|
|
+// [sort] sort
|
|
|
+// Reference: https://wg21.link/sort
|
|
|
+
|
|
|
+// Effects: Sorts the elements in the range `[first, last)` with respect to
|
|
|
+// `comp` and `proj`.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: Let `N` be `last - first`. `O(N log N)` comparisons and
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/sort#:~:text=ranges::sort(I
|
|
|
+template <typename RandomAccessIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<RandomAccessIterator, Proj>,
|
|
|
+ projected<RandomAccessIterator, Proj>>>
|
|
|
+constexpr auto sort(RandomAccessIterator first,
|
|
|
+ RandomAccessIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ std::sort(first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Effects: Sorts the elements in `range` with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: Let `N` be `size(range)`. `O(N log N)` comparisons and
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/sort#:~:text=ranges::sort(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto sort(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::sort(ranges::begin(range), ranges::end(range), std::move(comp),
|
|
|
+ std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [stable.sort] stable_sort
|
|
|
+// Reference: https://wg21.link/stable.sort
|
|
|
+
|
|
|
+// Effects: Sorts the elements in the range `[first, last)` with respect to
|
|
|
+// `comp` and `proj`.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: Let `N` be `last - first`. If enough extra memory is available,
|
|
|
+// `N log (N)` comparisons. Otherwise, at most `N log^2 (N)` comparisons. In
|
|
|
+// either case, twice as many projections as the number of comparisons.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/stable.sort#:~:text=ranges::stable_sort(I
|
|
|
+template <typename RandomAccessIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<RandomAccessIterator, Proj>,
|
|
|
+ projected<RandomAccessIterator, Proj>>>
|
|
|
+constexpr auto stable_sort(RandomAccessIterator first,
|
|
|
+ RandomAccessIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ std::stable_sort(first, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Effects: Sorts the elements in `range` with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Returns: `end(rang)`.
|
|
|
+//
|
|
|
+// Complexity: Let `N` be `size(range)`. If enough extra memory is available,
|
|
|
+// `N log (N)` comparisons. Otherwise, at most `N log^2 (N)` comparisons. In
|
|
|
+// either case, twice as many projections as the number of comparisons.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/stable.sort#:~:text=ranges::stable_sort(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto stable_sort(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::stable_sort(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [partial.sort] partial_sort
|
|
|
+// Reference: https://wg21.link/partial.sort
|
|
|
+
|
|
|
+// Preconditions: `[first, middle)` and `[middle, last)` are valid ranges.
|
|
|
+//
|
|
|
+// Effects: Places the first `middle - first` elements from the range
|
|
|
+// `[first, last)` as sorted with respect to `comp` and `proj` into the range
|
|
|
+// `[first, middle)`. The rest of the elements in the range `[middle, last)` are
|
|
|
+// placed in an unspecified order.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: Approximately `(last - first) * log(middle - first)` comparisons,
|
|
|
+// and twice as many projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/partial.sort#:~:text=ranges::partial_sort(I
|
|
|
+template <typename RandomAccessIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<RandomAccessIterator, Proj>,
|
|
|
+ projected<RandomAccessIterator, Proj>>>
|
|
|
+constexpr auto partial_sort(RandomAccessIterator first,
|
|
|
+ RandomAccessIterator middle,
|
|
|
+ RandomAccessIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ std::partial_sort(first, middle, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `[begin(range), middle)` and `[middle, end(range))` are valid
|
|
|
+// ranges.
|
|
|
+//
|
|
|
+// Effects: Places the first `middle - begin(range)` elements from `range` as
|
|
|
+// sorted with respect to `comp` and `proj` into the range
|
|
|
+// `[begin(range), middle)`. The rest of the elements in the range
|
|
|
+// `[middle, end(range))` are placed in an unspecified order.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: Approximately `size(range) * log(middle - begin(range))`
|
|
|
+// comparisons, and twice as many projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/partial.sort#:~:text=ranges::partial_sort(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto partial_sort(Range&& range,
|
|
|
+ iterator_t<Range> middle,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::partial_sort(ranges::begin(range), middle, ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [partial.sort.copy] partial_sort_copy
|
|
|
+// Reference: https://wg21.link/partial.sort.copy
|
|
|
+
|
|
|
+// Let `N` be `min(last - first, result_last - result_first)`.
|
|
|
+//
|
|
|
+// Preconditions: For iterators `a1` and `b1` in `[first, last)`, and iterators
|
|
|
+// `x2` and `y2` in `[result_first, result_last)`, after evaluating the
|
|
|
+// assignment `*y2 = *b1`, let `E` be the value of `bool(invoke(comp,
|
|
|
+// invoke(proj1, *a1), invoke(proj2, *y2)))`. Then, after evaluating the
|
|
|
+// assignment `*x2 = *a1`, `E` is equal to `bool(invoke(comp, invoke(proj2,
|
|
|
+// *x2), invoke(proj2, *y2)))`.
|
|
|
+//
|
|
|
+// Effects: Places the first `N` elements as sorted with respect to `comp` and
|
|
|
+// `proj2` into the range `[result_first, result_first + N)`.
|
|
|
+//
|
|
|
+// Returns: `result_first + N`.
|
|
|
+//
|
|
|
+// Complexity: Approximately `(last - first) * log N` comparisons, and twice as
|
|
|
+// many projections.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/partial.sort.copy#:~:text=ranges::partial_sort_copy(I1
|
|
|
+template <typename InputIterator,
|
|
|
+ typename RandomAccessIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator, Proj1>,
|
|
|
+ projected<RandomAccessIterator, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<RandomAccessIterator, Proj2>,
|
|
|
+ projected<InputIterator, Proj1>>>
|
|
|
+constexpr auto partial_sort_copy(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ RandomAccessIterator result_first,
|
|
|
+ RandomAccessIterator result_last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ // Needs to opt-in to all permutations, since std::partial_sort_copy expects
|
|
|
+ // comp(proj2(lhs), proj1(rhs)) to compile.
|
|
|
+ return std::partial_sort_copy(
|
|
|
+ first, last, result_first, result_last,
|
|
|
+ internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `min(size(range), size(result_range))`.
|
|
|
+//
|
|
|
+// Preconditions: For iterators `a1` and `b1` in `range`, and iterators
|
|
|
+// `x2` and `y2` in `result_range`, after evaluating the assignment
|
|
|
+// `*y2 = *b1`, let `E` be the value of
|
|
|
+// `bool(invoke(comp, invoke(proj1, *a1), invoke(proj2, *y2)))`. Then, after
|
|
|
+// evaluating the assignment `*x2 = *a1`, `E` is equal to
|
|
|
+// `bool(invoke(comp, invoke(proj2, *x2), invoke(proj2, *y2)))`.
|
|
|
+//
|
|
|
+// Effects: Places the first `N` elements as sorted with respect to `comp` and
|
|
|
+// `proj2` into the range `[begin(result_range), begin(result_range) + N)`.
|
|
|
+//
|
|
|
+// Returns: `begin(result_range) + N`.
|
|
|
+//
|
|
|
+// Complexity: Approximately `size(range) * log N` comparisons, and twice as
|
|
|
+// many projections.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/partial.sort.copy#:~:text=ranges::partial_sort_copy(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range2>, Proj2>,
|
|
|
+ projected<iterator_t<Range1>, Proj1>>>
|
|
|
+constexpr auto partial_sort_copy(Range1&& range,
|
|
|
+ Range2&& result_range,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::partial_sort_copy(ranges::begin(range), ranges::end(range),
|
|
|
+ ranges::begin(result_range),
|
|
|
+ ranges::end(result_range), std::move(comp),
|
|
|
+ std::move(proj1), std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [is.sorted] is_sorted
|
|
|
+// Reference: https://wg21.link/is.sorted
|
|
|
+
|
|
|
+// Returns: Whether the range `[first, last)` is sorted with respect to `comp`
|
|
|
+// and `proj`.
|
|
|
+//
|
|
|
+// Complexity: Linear.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/is.sorted#:~:text=ranges::is_sorted(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<ForwardIterator, Proj>,
|
|
|
+ projected<ForwardIterator, Proj>>>
|
|
|
+constexpr auto is_sorted(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::is_sorted(first, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: Whether `range` is sorted with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Complexity: Linear.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/is.sorted#:~:text=ranges::is_sorted(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto is_sorted(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::is_sorted(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: The last iterator `i` in `[first, last]` for which the range
|
|
|
+// `[first, i)` is sorted with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Complexity: Linear.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/is.sorted#:~:text=ranges::is_sorted_until(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<ForwardIterator, Proj>,
|
|
|
+ projected<ForwardIterator, Proj>>>
|
|
|
+constexpr auto is_sorted_until(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::is_sorted_until(
|
|
|
+ first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: The last iterator `i` in `[begin(range), end(range)]` for which the
|
|
|
+// range `[begin(range), i)` is sorted with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Complexity: Linear.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/is.sorted#:~:text=ranges::is_sorted_until(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto is_sorted_until(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::is_sorted_until(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.nth.element] Nth element
|
|
|
+// Reference: https://wg21.link/alg.nth.element
|
|
|
+
|
|
|
+// Preconditions: `[first, nth)` and `[nth, last)` are valid ranges.
|
|
|
+//
|
|
|
+// Effects: After `nth_element` the element in the position pointed to by `nth`
|
|
|
+// is the element that would be in that position if the whole range were sorted
|
|
|
+// with respect to `comp` and `proj`, unless `nth == last`. Also for every
|
|
|
+// iterator `i` in the range `[first, nth)` and every iterator `j` in the range
|
|
|
+// `[nth, last)` it holds that:
|
|
|
+// `bool(invoke(comp, invoke(proj, *j), invoke(proj, *i)))` is false.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: Linear on average.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.nth.element#:~:text=ranges::nth_element(I
|
|
|
+template <typename RandomAccessIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<RandomAccessIterator, Proj>,
|
|
|
+ projected<RandomAccessIterator, Proj>>>
|
|
|
+constexpr auto nth_element(RandomAccessIterator first,
|
|
|
+ RandomAccessIterator nth,
|
|
|
+ RandomAccessIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ std::nth_element(first, nth, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `[begin(range), nth)` and `[nth, end(range))` are valid
|
|
|
+// ranges.
|
|
|
+//
|
|
|
+// Effects: After `nth_element` the element in the position pointed to by `nth`
|
|
|
+// is the element that would be in that position if the whole range were sorted
|
|
|
+// with respect to `comp` and `proj`, unless `nth == end(range)`. Also for every
|
|
|
+// iterator `i` in the range `[begin(range), nth)` and every iterator `j` in the
|
|
|
+// range `[nth, end(range))` it holds that:
|
|
|
+// `bool(invoke(comp, invoke(proj, *j), invoke(proj, *i)))` is false.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: Linear on average.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.nth.element#:~:text=ranges::nth_element(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto nth_element(Range&& range,
|
|
|
+ iterator_t<Range> nth,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::nth_element(ranges::begin(range), nth, ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.binary.search] Binary search
|
|
|
+// Reference: https://wg21.link/alg.binary.search
|
|
|
+
|
|
|
+// [lower.bound] lower_bound
|
|
|
+// Reference: https://wg21.link/lower.bound
|
|
|
+
|
|
|
+// Preconditions: The elements `e` of `[first, last)` are partitioned with
|
|
|
+// respect to the expression `bool(invoke(comp, invoke(proj, e), value))`.
|
|
|
+//
|
|
|
+// Returns: The furthermost iterator `i` in the range `[first, last]` such that
|
|
|
+// for every iterator `j` in the range `[first, i)`,
|
|
|
+// `bool(invoke(comp, invoke(proj, *j), value))` is true.
|
|
|
+//
|
|
|
+// Complexity: At most `log_2(last - first) + O(1)` comparisons and projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/lower.bound#:~:text=ranges::lower_bound(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename T,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto lower_bound(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ const T& value,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ // The second arg is guaranteed to be `value`, so we'll simply apply the
|
|
|
+ // identity projection.
|
|
|
+ identity value_proj;
|
|
|
+ return std::lower_bound(
|
|
|
+ first, last, value,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, value_proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: The elements `e` of `range` are partitioned with respect to
|
|
|
+// the expression `bool(invoke(comp, invoke(proj, e), value))`.
|
|
|
+//
|
|
|
+// Returns: The furthermost iterator `i` in the range
|
|
|
+// `[begin(range), end(range)]` such that for every iterator `j` in the range
|
|
|
+// `[begin(range), i)`, `bool(invoke(comp, invoke(proj, *j), value))` is true.
|
|
|
+//
|
|
|
+// Complexity: At most `log_2(size(range)) + O(1)` comparisons and projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/lower.bound#:~:text=ranges::lower_bound(R
|
|
|
+template <typename Range,
|
|
|
+ typename T,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto lower_bound(Range&& range,
|
|
|
+ const T& value,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::lower_bound(ranges::begin(range), ranges::end(range), value,
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [upper.bound] upper_bound
|
|
|
+// Reference: https://wg21.link/upper.bound
|
|
|
+
|
|
|
+// Preconditions: The elements `e` of `[first, last)` are partitioned with
|
|
|
+// respect to the expression `!bool(invoke(comp, value, invoke(proj, e)))`.
|
|
|
+//
|
|
|
+// Returns: The furthermost iterator `i` in the range `[first, last]` such that
|
|
|
+// for every iterator `j` in the range `[first, i)`,
|
|
|
+// `!bool(invoke(comp, value, invoke(proj, *j)))` is true.
|
|
|
+//
|
|
|
+// Complexity: At most `log_2(last - first) + O(1)` comparisons and projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/upper.bound#:~:text=ranges::upper_bound(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename T,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto upper_bound(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ const T& value,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ // The first arg is guaranteed to be `value`, so we'll simply apply the
|
|
|
+ // identity projection.
|
|
|
+ identity value_proj;
|
|
|
+ return std::upper_bound(
|
|
|
+ first, last, value,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, value_proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: The elements `e` of `range` are partitioned with
|
|
|
+// respect to the expression `!bool(invoke(comp, value, invoke(proj, e)))`.
|
|
|
+//
|
|
|
+// Returns: The furthermost iterator `i` in the range
|
|
|
+// `[begin(range), end(range)]` such that for every iterator `j` in the range
|
|
|
+// `[begin(range), i)`, `!bool(invoke(comp, value, invoke(proj, *j)))` is true.
|
|
|
+//
|
|
|
+// Complexity: At most `log_2(size(range)) + O(1)` comparisons and projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/upper.bound#:~:text=ranges::upper_bound(R
|
|
|
+template <typename Range,
|
|
|
+ typename T,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto upper_bound(Range&& range,
|
|
|
+ const T& value,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::upper_bound(ranges::begin(range), ranges::end(range), value,
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [equal.range] equal_range
|
|
|
+// Reference: https://wg21.link/equal.range
|
|
|
+
|
|
|
+// Preconditions: The elements `e` of `[first, last)` are partitioned with
|
|
|
+// respect to the expressions `bool(invoke(comp, invoke(proj, e), value))` and
|
|
|
+// `!bool(invoke(comp, value, invoke(proj, e)))`.
|
|
|
+//
|
|
|
+// Returns: `{ranges::lower_bound(first, last, value, comp, proj),
|
|
|
+// ranges::upper_bound(first, last, value, comp, proj)}`.
|
|
|
+//
|
|
|
+// Complexity: At most 2 ∗ log_2(last - first) + O(1) comparisons and
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/equal.range#:~:text=ranges::equal_range(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename T,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto equal_range(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ const T& value,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ // Note: This does not dispatch to std::equal_range, as otherwise it would not
|
|
|
+ // be possible to prevent applying `proj` to `value`, which can result in
|
|
|
+ // unintended behavior.
|
|
|
+ return std::make_pair(ranges::lower_bound(first, last, value, comp, proj),
|
|
|
+ ranges::upper_bound(first, last, value, comp, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: The elements `e` of `range` are partitioned with
|
|
|
+// respect to the expressions `bool(invoke(comp, invoke(proj, e), value))` and
|
|
|
+// `!bool(invoke(comp, value, invoke(proj, e)))`.
|
|
|
+//
|
|
|
+// Returns: `{ranges::lower_bound(range, value, comp, proj),
|
|
|
+// ranges::upper_bound(range, value, comp, proj)}`.
|
|
|
+//
|
|
|
+// Complexity: At most 2 ∗ log_2(size(range)) + O(1) comparisons and
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/equal.range#:~:text=ranges::equal_range(R
|
|
|
+template <typename Range,
|
|
|
+ typename T,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto equal_range(Range&& range,
|
|
|
+ const T& value,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::equal_range(ranges::begin(range), ranges::end(range), value,
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [binary.search] binary_search
|
|
|
+// Reference: https://wg21.link/binary.search
|
|
|
+
|
|
|
+// Preconditions: The elements `e` of `[first, last)` are partitioned with
|
|
|
+// respect to the expressions `bool(invoke(comp, invoke(proj, e), value))` and
|
|
|
+// `!bool(invoke(comp, value, invoke(proj, e)))`.
|
|
|
+//
|
|
|
+// Returns: `true` if and only if for some iterator `i` in the range
|
|
|
+// `[first, last)`, `!bool(invoke(comp, invoke(proj, *i), value)) &&
|
|
|
+// !bool(invoke(comp, value, invoke(proj, *i)))` is true.
|
|
|
+//
|
|
|
+// Complexity: At most `log_2(last - first) + O(1)` comparisons and projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/binary.search#:~:text=ranges::binary_search(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename T,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto binary_search(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ const T& value,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ first = ranges::lower_bound(first, last, value, comp, proj);
|
|
|
+ return first != last &&
|
|
|
+ !base::invoke(comp, value, base::invoke(proj, *first));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: The elements `e` of `range` are partitioned with
|
|
|
+// respect to the expressions `bool(invoke(comp, invoke(proj, e), value))` and
|
|
|
+// `!bool(invoke(comp, value, invoke(proj, e)))`.
|
|
|
+//
|
|
|
+// Returns: `true` if and only if for some iterator `i` in `range`
|
|
|
+// `!bool(invoke(comp, invoke(proj, *i), value)) &&
|
|
|
+// !bool(invoke(comp, value, invoke(proj, *i)))` is true.
|
|
|
+//
|
|
|
+// Complexity: At most `log_2(size(range)) + O(1)` comparisons and projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/binary.search#:~:text=ranges::binary_search(R
|
|
|
+template <typename Range,
|
|
|
+ typename T,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto binary_search(Range&& range,
|
|
|
+ const T& value,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::binary_search(ranges::begin(range), ranges::end(range), value,
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.partitions] Partitions
|
|
|
+// Reference: https://wg21.link/alg.partitions
|
|
|
+
|
|
|
+// Returns: `true` if and only if the elements `e` of `[first, last)` are
|
|
|
+// partitioned with respect to the expression
|
|
|
+// `bool(invoke(pred, invoke(proj, e)))`.
|
|
|
+//
|
|
|
+// Complexity: Linear. At most `last - first` applications of `pred` and `proj`.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.partitions#:~:text=ranges::is_partitioned(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto is_partitioned(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::is_partitioned(first, last,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: `true` if and only if the elements `e` of `range` are partitioned
|
|
|
+// with respect to the expression `bool(invoke(pred, invoke(proj, e)))`.
|
|
|
+//
|
|
|
+// Complexity: Linear. At most `size(range)` applications of `pred` and `proj`.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.partitions#:~:text=ranges::is_partitioned(R
|
|
|
+template <typename Range,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto is_partitioned(Range&& range, Pred pred, Proj proj = {}) {
|
|
|
+ return ranges::is_partitioned(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
|
|
|
+//
|
|
|
+// Effects: Places all the elements `e` in `[first, last)` that satisfy `E(e)`
|
|
|
+// before all the elements that do not.
|
|
|
+//
|
|
|
+// Returns: Let `i` be an iterator such that `E(*j)` is `true` for every
|
|
|
+// iterator `j` in `[first, i)` and `false` for every iterator `j` in
|
|
|
+// `[i, last)`. Returns: i.
|
|
|
+//
|
|
|
+// Complexity: Let `N = last - first`:
|
|
|
+// Exactly `N` applications of the predicate and projection. At most `N / 2`
|
|
|
+// swaps if the type of `first` models `bidirectional_iterator`, and at most `N`
|
|
|
+// swaps otherwise.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto partition(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::partition(first, last,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
|
|
|
+//
|
|
|
+// Effects: Places all the elements `e` in `range` that satisfy `E(e)` before
|
|
|
+// all the elements that do not.
|
|
|
+//
|
|
|
+// Returns: Let `i` be an iterator such that `E(*j)` is `true` for every
|
|
|
+// iterator `j` in `[begin(range), i)` and `false` for every iterator `j` in
|
|
|
+// `[i, last)`. Returns: i.
|
|
|
+//
|
|
|
+// Complexity: Let `N = size(range)`:
|
|
|
+// Exactly `N` applications of the predicate and projection. At most `N / 2`
|
|
|
+// swaps if the type of `first` models `bidirectional_iterator`, and at most `N`
|
|
|
+// swaps otherwise.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition(R
|
|
|
+template <typename Range,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto partition(Range&& range, Pred pred, Proj proj = {}) {
|
|
|
+ return ranges::partition(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
|
|
|
+//
|
|
|
+// Effects: Places all the elements `e` in `[first, last)` that satisfy `E(e)`
|
|
|
+// before all the elements that do not. The relative order of the elements in
|
|
|
+// both groups is preserved.
|
|
|
+//
|
|
|
+// Returns: Let `i` be an iterator such that for every iterator `j` in
|
|
|
+// `[first, i)`, `E(*j)` is `true`, and for every iterator `j` in the range
|
|
|
+// `[i, last)`, `E(*j)` is `false`. Returns: `i`.
|
|
|
+//
|
|
|
+// Complexity: Let `N = last - first`:
|
|
|
+// At most `N log N` swaps, but only `O(N)` swaps if there is enough extra
|
|
|
+// memory. Exactly `N` applications of the predicate and projection.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.partitions#:~:text=ranges::stable_partition(I
|
|
|
+template <typename BidirectionalIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator>>
|
|
|
+constexpr auto stable_partition(BidirectionalIterator first,
|
|
|
+ BidirectionalIterator last,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::stable_partition(first, last,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
|
|
|
+//
|
|
|
+// Effects: Places all the elements `e` in `range` that satisfy `E(e)` before
|
|
|
+// all the elements that do not. The relative order of the elements in both
|
|
|
+// groups is preserved.
|
|
|
+//
|
|
|
+// Returns: Let `i` be an iterator such that for every iterator `j` in
|
|
|
+// `[begin(range), i)`, `E(*j)` is `true`, and for every iterator `j` in the
|
|
|
+// range `[i, end(range))`, `E(*j)` is `false`. Returns: `i`.
|
|
|
+//
|
|
|
+// Complexity: Let `N = size(range)`:
|
|
|
+// At most `N log N` swaps, but only `O(N)` swaps if there is enough extra
|
|
|
+// memory. Exactly `N` applications of the predicate and projection.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.partitions#:~:text=ranges::stable_partition(R
|
|
|
+template <typename Range,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto stable_partition(Range&& range, Pred pred, Proj proj = {}) {
|
|
|
+ return ranges::stable_partition(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
|
|
|
+//
|
|
|
+// Mandates: The expression `*first` is writable to `out_true` and `out_false`.
|
|
|
+//
|
|
|
+// Preconditions: The input range and output ranges do not overlap.
|
|
|
+//
|
|
|
+// Effects: For each iterator `i` in `[first, last)`, copies `*i` to the output
|
|
|
+// range beginning with `out_true` if `E(*i)` is `true`, or to the output range
|
|
|
+// beginning with `out_false` otherwise.
|
|
|
+//
|
|
|
+// Returns: Let `o1` be the end of the output range beginning at `out_true`, and
|
|
|
+// `o2` the end of the output range beginning at `out_false`.
|
|
|
+// Returns `{o1, o2}`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `last - first` applications of `pred` and `proj`.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition_copy(I
|
|
|
+template <typename InputIterator,
|
|
|
+ typename OutputIterator1,
|
|
|
+ typename OutputIterator2,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator1>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator2>>
|
|
|
+constexpr auto partition_copy(InputIterator first,
|
|
|
+ InputIterator last,
|
|
|
+ OutputIterator1 out_true,
|
|
|
+ OutputIterator2 out_false,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::partition_copy(first, last, out_true, out_false,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
|
|
|
+//
|
|
|
+// Mandates: The expression `*begin(range)` is writable to `out_true` and
|
|
|
+// `out_false`.
|
|
|
+//
|
|
|
+// Preconditions: The input range and output ranges do not overlap.
|
|
|
+//
|
|
|
+// Effects: For each iterator `i` in `range`, copies `*i` to the output range
|
|
|
+// beginning with `out_true` if `E(*i)` is `true`, or to the output range
|
|
|
+// beginning with `out_false` otherwise.
|
|
|
+//
|
|
|
+// Returns: Let `o1` be the end of the output range beginning at `out_true`, and
|
|
|
+// `o2` the end of the output range beginning at `out_false`.
|
|
|
+// Returns `{o1, o2}`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range)` applications of `pred` and `proj`.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition_copy(R
|
|
|
+template <typename Range,
|
|
|
+ typename OutputIterator1,
|
|
|
+ typename OutputIterator2,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator1>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator2>>
|
|
|
+constexpr auto partition_copy(Range&& range,
|
|
|
+ OutputIterator1 out_true,
|
|
|
+ OutputIterator2 out_false,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::partition_copy(ranges::begin(range), ranges::end(range),
|
|
|
+ out_true, out_false, std::move(pred),
|
|
|
+ std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
|
|
|
+//
|
|
|
+// Preconditions: The elements `e` of `[first, last)` are partitioned with
|
|
|
+// respect to `E(e)`.
|
|
|
+//
|
|
|
+// Returns: An iterator `mid` such that `E(*i)` is `true` for all iterators `i`
|
|
|
+// in `[first, mid)`, and `false` for all iterators `i` in `[mid, last)`.
|
|
|
+//
|
|
|
+// Complexity: `O(log(last - first))` applications of `pred` and `proj`.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition_point(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>>
|
|
|
+constexpr auto partition_point(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Pred pred,
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::partition_point(first, last,
|
|
|
+ internal::ProjectedUnaryPredicate(pred, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// let `E(x)` be `bool(invoke(pred, invoke(proj, x)))`.
|
|
|
+//
|
|
|
+// Preconditions: The elements `e` of `range` are partitioned with respect to
|
|
|
+// `E(e)`.
|
|
|
+//
|
|
|
+// Returns: An iterator `mid` such that `E(*i)` is `true` for all iterators `i`
|
|
|
+// in `[begin(range), mid)`, and `false` for all iterators `i` in
|
|
|
+// `[mid, end(range))`.
|
|
|
+//
|
|
|
+// Complexity: `O(log(size(range)))` applications of `pred` and `proj`.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.partitions#:~:text=ranges::partition_point(R
|
|
|
+template <typename Range,
|
|
|
+ typename Pred,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto partition_point(Range&& range, Pred pred, Proj proj = {}) {
|
|
|
+ return ranges::partition_point(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(pred), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.merge] Merge
|
|
|
+// Reference: https://wg21.link/alg.merge
|
|
|
+
|
|
|
+// Let `N` be `(last1 - first1) + (last2 - first2)`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
|
|
|
+// with respect to `comp` and `proj1` or `proj2`, respectively. The resulting
|
|
|
+// range does not overlap with either of the original ranges.
|
|
|
+//
|
|
|
+// Effects: Copies all the elements of the two ranges `[first1, last1)` and
|
|
|
+// `[first2, last2)` into the range `[result, result_last)`, where `result_last`
|
|
|
+// is `result + N`. If an element `a` precedes `b` in an input range, `a` is
|
|
|
+// copied into the output range before `b`. If `e1` is an element of
|
|
|
+// `[first1, last1)` and `e2` of `[first2, last2)`, `e2` is copied into the
|
|
|
+// output range before `e1` if and only if
|
|
|
+// `bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))` is `true`.
|
|
|
+//
|
|
|
+// Returns: `result_last`.
|
|
|
+//
|
|
|
+// Complexity: At most `N - 1` comparisons and applications of each projection.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.merge#:~:text=ranges::merge(I1
|
|
|
+template <typename InputIterator1,
|
|
|
+ typename InputIterator2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator1>,
|
|
|
+ typename = internal::iterator_category_t<InputIterator2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator1, Proj1>,
|
|
|
+ projected<InputIterator2, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator2, Proj2>,
|
|
|
+ projected<InputIterator1, Proj1>>>
|
|
|
+constexpr auto merge(InputIterator1 first1,
|
|
|
+ InputIterator1 last1,
|
|
|
+ InputIterator2 first2,
|
|
|
+ InputIterator2 last2,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ // Needs to opt-in to all permutations, since std::merge expects
|
|
|
+ // comp(proj2(lhs), proj1(rhs)) to compile.
|
|
|
+ return std::merge(
|
|
|
+ first1, last1, first2, last2, result,
|
|
|
+ internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Let `N` be `size(range1) + size(range2)`.
|
|
|
+//
|
|
|
+// Preconditions: The ranges `range1` and `range2` are sorted with respect to
|
|
|
+// `comp` and `proj1` or `proj2`, respectively. The resulting range does not
|
|
|
+// overlap with either of the original ranges.
|
|
|
+//
|
|
|
+// Effects: Copies all the elements of the two ranges `range1` and `range2` into
|
|
|
+// the range `[result, result_last)`, where `result_last` is `result + N`. If an
|
|
|
+// element `a` precedes `b` in an input range, `a` is copied into the output
|
|
|
+// range before `b`. If `e1` is an element of `range1` and `e2` of `range2`,
|
|
|
+// `e2` is copied into the output range before `e1` if and only if
|
|
|
+// `bool(invoke(comp, invoke(proj2, e2), invoke(proj1, e1)))` is `true`.
|
|
|
+//
|
|
|
+// Returns: `result_last`.
|
|
|
+//
|
|
|
+// Complexity: At most `N - 1` comparisons and applications of each projection.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.merge#:~:text=ranges::merge(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range2>, Proj2>,
|
|
|
+ projected<iterator_t<Range1>, Proj1>>>
|
|
|
+constexpr auto merge(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::merge(ranges::begin(range1), ranges::end(range1),
|
|
|
+ ranges::begin(range2), ranges::end(range2), result,
|
|
|
+ std::move(comp), std::move(proj1), std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `[first, middle)` and `[middle, last)` are valid ranges sorted
|
|
|
+// with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Effects: Merges two sorted consecutive ranges `[first, middle)` and
|
|
|
+// `[middle, last)`, putting the result of the merge into the range
|
|
|
+// `[first, last)`. The resulting range is sorted with respect to `comp` and
|
|
|
+// `proj`.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: Let `N = last - first`: If enough additional memory is available,
|
|
|
+// exactly `N - 1` comparisons. Otherwise, `O(N log N)` comparisons. In either
|
|
|
+// case, twice as many projections as comparisons.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.merge#:~:text=ranges::inplace_merge(I
|
|
|
+template <typename BidirectionalIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator>>
|
|
|
+constexpr auto inplace_merge(BidirectionalIterator first,
|
|
|
+ BidirectionalIterator middle,
|
|
|
+ BidirectionalIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ std::inplace_merge(first, middle, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `[begin(range), middle)` and `[middle, end(range))` are valid
|
|
|
+// ranges sorted with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Effects: Merges two sorted consecutive ranges `[begin(range), middle)` and
|
|
|
+// `[middle, end(range))`, putting the result of the merge into `range`. The
|
|
|
+// resulting range is sorted with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: Let `N = size(range)`: If enough additional memory is available,
|
|
|
+// exactly `N - 1` comparisons. Otherwise, `O(N log N)` comparisons. In either
|
|
|
+// case, twice as many projections as comparisons.
|
|
|
+//
|
|
|
+// Remarks: Stable.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.merge#:~:text=ranges::inplace_merge(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto inplace_merge(Range&& range,
|
|
|
+ iterator_t<Range> middle,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return ranges::inplace_merge(ranges::begin(range), middle, ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.set.operations] Set operations on sorted structures
|
|
|
+// Reference: https://wg21.link/alg.set.operations
|
|
|
+
|
|
|
+// [includes] includes
|
|
|
+// Reference: https://wg21.link/includes
|
|
|
+
|
|
|
+// Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
|
|
|
+// with respect to `comp` and `proj1` or `proj2`, respectively.
|
|
|
+//
|
|
|
+// Returns: `true` if and only if `[first2, last2)` is a subsequence of
|
|
|
+// `[first1, last1)`.
|
|
|
+//
|
|
|
+// Complexity: At most `2 * ((last1 - first1) + (last2 - first2)) - 1`
|
|
|
+// comparisons and applications of each projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/includes#:~:text=ranges::includes(I1
|
|
|
+template <typename InputIterator1,
|
|
|
+ typename InputIterator2,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator1>,
|
|
|
+ typename = internal::iterator_category_t<InputIterator2>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator1, Proj1>,
|
|
|
+ projected<InputIterator2, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator2, Proj2>,
|
|
|
+ projected<InputIterator1, Proj1>>>
|
|
|
+constexpr auto includes(InputIterator1 first1,
|
|
|
+ InputIterator1 last1,
|
|
|
+ InputIterator2 first2,
|
|
|
+ InputIterator2 last2,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ // Needs to opt-in to all permutations, since std::includes expects
|
|
|
+ // comp(proj1(lhs), proj2(rhs)) and comp(proj2(lhs), proj1(rhs)) to compile.
|
|
|
+ return std::includes(
|
|
|
+ first1, last1, first2, last2,
|
|
|
+ internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: The ranges `range1` and `range2` are sorted with respect to
|
|
|
+// `comp` and `proj1` or `proj2`, respectively.
|
|
|
+//
|
|
|
+// Returns: `true` if and only if `range2` is a subsequence of `range1`.
|
|
|
+//
|
|
|
+// Complexity: At most `2 * (size(range1) + size(range2)) - 1` comparisons and
|
|
|
+// applications of each projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/includes#:~:text=ranges::includes(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range2>, Proj2>,
|
|
|
+ projected<iterator_t<Range1>, Proj1>>>
|
|
|
+constexpr auto includes(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::includes(ranges::begin(range1), ranges::end(range1),
|
|
|
+ ranges::begin(range2), ranges::end(range2),
|
|
|
+ std::move(comp), std::move(proj1), std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [set.union] set_union
|
|
|
+// Reference: https://wg21.link/set.union
|
|
|
+
|
|
|
+// Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
|
|
|
+// with respect to `comp` and `proj1` or `proj2`, respectively. The resulting
|
|
|
+// range does not overlap with either of the original ranges.
|
|
|
+//
|
|
|
+// Effects: Constructs a sorted union of the elements from the two ranges; that
|
|
|
+// is, the set of elements that are present in one or both of the ranges.
|
|
|
+//
|
|
|
+// Returns: The end of the constructed range.
|
|
|
+//
|
|
|
+// Complexity: At most `2 * ((last1 - first1) + (last2 - first2)) - 1`
|
|
|
+// comparisons and applications of each projection.
|
|
|
+//
|
|
|
+// Remarks: Stable. If `[first1, last1)` contains `m` elements that are
|
|
|
+// equivalent to each other and `[first2, last2)` contains `n` elements that are
|
|
|
+// equivalent to them, then all `m` elements from the first range are copied to
|
|
|
+// the output range, in order, and then the final `max(n - m , 0)` elements from
|
|
|
+// the second range are copied to the output range, in order.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/set.union#:~:text=ranges::set_union(I1
|
|
|
+template <typename InputIterator1,
|
|
|
+ typename InputIterator2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator1>,
|
|
|
+ typename = internal::iterator_category_t<InputIterator2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator1, Proj1>,
|
|
|
+ projected<InputIterator2, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator2, Proj2>,
|
|
|
+ projected<InputIterator1, Proj1>>>
|
|
|
+constexpr auto set_union(InputIterator1 first1,
|
|
|
+ InputIterator1 last1,
|
|
|
+ InputIterator2 first2,
|
|
|
+ InputIterator2 last2,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ // Needs to opt-in to all permutations, since std::set_union expects
|
|
|
+ // comp(proj1(lhs), proj2(rhs)) and comp(proj2(lhs), proj1(rhs)) to compile.
|
|
|
+ return std::set_union(
|
|
|
+ first1, last1, first2, last2, result,
|
|
|
+ internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: The ranges `range1` and `range2` are sorted with respect to
|
|
|
+// `comp` and `proj1` or `proj2`, respectively. The resulting range does not
|
|
|
+// overlap with either of the original ranges.
|
|
|
+//
|
|
|
+// Effects: Constructs a sorted union of the elements from the two ranges; that
|
|
|
+// is, the set of elements that are present in one or both of the ranges.
|
|
|
+//
|
|
|
+// Returns: The end of the constructed range.
|
|
|
+//
|
|
|
+// Complexity: At most `2 * (size(range1) + size(range2)) - 1` comparisons and
|
|
|
+// applications of each projection.
|
|
|
+//
|
|
|
+// Remarks: Stable. If `range1` contains `m` elements that are equivalent to
|
|
|
+// each other and `range2` contains `n` elements that are equivalent to them,
|
|
|
+// then all `m` elements from the first range are copied to the output range, in
|
|
|
+// order, and then the final `max(n - m , 0)` elements from the second range are
|
|
|
+// copied to the output range, in order.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/set.union#:~:text=ranges::set_union(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range2>, Proj2>,
|
|
|
+ projected<iterator_t<Range1>, Proj1>>>
|
|
|
+constexpr auto set_union(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::set_union(ranges::begin(range1), ranges::end(range1),
|
|
|
+ ranges::begin(range2), ranges::end(range2), result,
|
|
|
+ std::move(comp), std::move(proj1), std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [set.intersection] set_intersection
|
|
|
+// Reference: https://wg21.link/set.intersection
|
|
|
+
|
|
|
+// Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
|
|
|
+// with respect to `comp` and `proj1` or `proj2`, respectively. The resulting
|
|
|
+// range does not overlap with either of the original ranges.
|
|
|
+//
|
|
|
+// Effects: Constructs a sorted intersection of the elements from the two
|
|
|
+// ranges; that is, the set of elements that are present in both of the ranges.
|
|
|
+//
|
|
|
+// Returns: The end of the constructed range.
|
|
|
+//
|
|
|
+// Complexity: At most `2 * ((last1 - first1) + (last2 - first2)) - 1`
|
|
|
+// comparisons and applications of each projection.
|
|
|
+//
|
|
|
+// Remarks: Stable. If `[first1, last1)` contains `m` elements that are
|
|
|
+// equivalent to each other and `[first2, last2)` contains `n` elements that are
|
|
|
+// equivalent to them, the first `min(m, n)` elements are copied from the first
|
|
|
+// range to the output range, in order.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/set.intersection#:~:text=ranges::set_intersection(I1
|
|
|
+template <typename InputIterator1,
|
|
|
+ typename InputIterator2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator1>,
|
|
|
+ typename = internal::iterator_category_t<InputIterator2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator1, Proj1>,
|
|
|
+ projected<InputIterator2, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator2, Proj2>,
|
|
|
+ projected<InputIterator1, Proj1>>>
|
|
|
+constexpr auto set_intersection(InputIterator1 first1,
|
|
|
+ InputIterator1 last1,
|
|
|
+ InputIterator2 first2,
|
|
|
+ InputIterator2 last2,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ // Needs to opt-in to all permutations, since std::set_intersection expects
|
|
|
+ // comp(proj1(lhs), proj2(rhs)) and comp(proj2(lhs), proj1(rhs)) to compile.
|
|
|
+ return std::set_intersection(
|
|
|
+ first1, last1, first2, last2, result,
|
|
|
+ internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: The ranges `range1` and `range2` are sorted with respect to
|
|
|
+// `comp` and `proj1` or `proj2`, respectively. The resulting range does not
|
|
|
+// overlap with either of the original ranges.
|
|
|
+//
|
|
|
+// Effects: Constructs a sorted intersection of the elements from the two
|
|
|
+// ranges; that is, the set of elements that are present in both of the ranges.
|
|
|
+//
|
|
|
+// Returns: The end of the constructed range.
|
|
|
+//
|
|
|
+// Complexity: At most `2 * (size(range1) + size(range2)) - 1` comparisons and
|
|
|
+// applications of each projection.
|
|
|
+//
|
|
|
+// Remarks: Stable. If `range1` contains `m` elements that are equivalent to
|
|
|
+// each other and `range2` contains `n` elements that are equivalent to them,
|
|
|
+// the first `min(m, n)` elements are copied from the first range to the output
|
|
|
+// range, in order.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/set.intersection#:~:text=ranges::set_intersection(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range2>, Proj2>,
|
|
|
+ projected<iterator_t<Range1>, Proj1>>>
|
|
|
+constexpr auto set_intersection(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::set_intersection(ranges::begin(range1), ranges::end(range1),
|
|
|
+ ranges::begin(range2), ranges::end(range2),
|
|
|
+ result, std::move(comp), std::move(proj1),
|
|
|
+ std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [set.difference] set_difference
|
|
|
+// Reference: https://wg21.link/set.difference
|
|
|
+
|
|
|
+// Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
|
|
|
+// with respect to `comp` and `proj1` or `proj2`, respectively. The resulting
|
|
|
+// range does not overlap with either of the original ranges.
|
|
|
+//
|
|
|
+// Effects: Copies the elements of the range `[first1, last1)` which are not
|
|
|
+// present in the range `[first2, last2)` to the range beginning at `result`.
|
|
|
+// The elements in the constructed range are sorted.
|
|
|
+//
|
|
|
+// Returns: The end of the constructed range.
|
|
|
+//
|
|
|
+// Complexity: At most `2 * ((last1 - first1) + (last2 - first2)) - 1`
|
|
|
+// comparisons and applications of each projection.
|
|
|
+//
|
|
|
+// Remarks: If `[first1, last1)` contains `m` elements that are equivalent to
|
|
|
+// each other and `[first2, last2)` contains `n` elements that are equivalent to
|
|
|
+// them, the last `max(m - n, 0)` elements from `[first1, last1)` are copied to
|
|
|
+// the output range, in order.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/set.difference#:~:text=ranges::set_difference(I1
|
|
|
+template <typename InputIterator1,
|
|
|
+ typename InputIterator2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator1>,
|
|
|
+ typename = internal::iterator_category_t<InputIterator2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator1, Proj1>,
|
|
|
+ projected<InputIterator2, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator2, Proj2>,
|
|
|
+ projected<InputIterator1, Proj1>>>
|
|
|
+constexpr auto set_difference(InputIterator1 first1,
|
|
|
+ InputIterator1 last1,
|
|
|
+ InputIterator2 first2,
|
|
|
+ InputIterator2 last2,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ // Needs to opt-in to all permutations, since std::set_difference expects
|
|
|
+ // comp(proj1(lhs), proj2(rhs)) and comp(proj2(lhs), proj1(rhs)) to compile.
|
|
|
+ return std::set_difference(
|
|
|
+ first1, last1, first2, last2, result,
|
|
|
+ internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: The ranges `range1` and `range2` are sorted with respect to
|
|
|
+// `comp` and `proj1` or `proj2`, respectively. The resulting range does not
|
|
|
+// overlap with either of the original ranges.
|
|
|
+//
|
|
|
+// Effects: Copies the elements of `range1` which are not present in `range2`
|
|
|
+// to the range beginning at `result`. The elements in the constructed range are
|
|
|
+// sorted.
|
|
|
+//
|
|
|
+// Returns: The end of the constructed range.
|
|
|
+//
|
|
|
+// Complexity: At most `2 * (size(range1) + size(range2)) - 1` comparisons and
|
|
|
+// applications of each projection.
|
|
|
+//
|
|
|
+// Remarks: Stable. If `range1` contains `m` elements that are equivalent to
|
|
|
+// each other and `range2` contains `n` elements that are equivalent to them,
|
|
|
+// the last `max(m - n, 0)` elements from `range1` are copied to the output
|
|
|
+// range, in order.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/set.difference#:~:text=ranges::set_difference(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range2>, Proj2>,
|
|
|
+ projected<iterator_t<Range1>, Proj1>>>
|
|
|
+constexpr auto set_difference(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::set_difference(ranges::begin(range1), ranges::end(range1),
|
|
|
+ ranges::begin(range2), ranges::end(range2),
|
|
|
+ result, std::move(comp), std::move(proj1),
|
|
|
+ std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [set.symmetric.difference] set_symmetric_difference
|
|
|
+// Reference: https://wg21.link/set.symmetric.difference
|
|
|
+
|
|
|
+// Preconditions: The ranges `[first1, last1)` and `[first2, last2)` are sorted
|
|
|
+// with respect to `comp` and `proj1` or `proj2`, respectively. The resulting
|
|
|
+// range does not overlap with either of the original ranges.
|
|
|
+//
|
|
|
+// Effects: Copies the elements of the range `[first1, last1)` that are not
|
|
|
+// present in the range `[first2, last2)`, and the elements of the range
|
|
|
+// `[first2, last2)` that are not present in the range `[first1, last1)` to the
|
|
|
+// range beginning at `result`. The elements in the constructed range are
|
|
|
+// sorted.
|
|
|
+//
|
|
|
+// Returns: The end of the constructed range.
|
|
|
+//
|
|
|
+// Complexity: At most `2 * ((last1 - first1) + (last2 - first2)) - 1`
|
|
|
+// comparisons and applications of each projection.
|
|
|
+//
|
|
|
+// Remarks: Stable. If `[first1, last1)` contains `m` elements that are
|
|
|
+// equivalent to each other and `[first2, last2)` contains `n` elements that are
|
|
|
+// equivalent to them, then `|m - n|` of those elements shall be copied to the
|
|
|
+// output range: the last `m - n` of these elements from `[first1, last1)` if
|
|
|
+// `m > n`, and the last `n - m` of these elements from `[first2, last2)` if
|
|
|
+// `m < n`. In either case, the elements are copied in order.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/set.symmetric.difference#:~:text=set_symmetric_difference(I1
|
|
|
+template <typename InputIterator1,
|
|
|
+ typename InputIterator2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<InputIterator1>,
|
|
|
+ typename = internal::iterator_category_t<InputIterator2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator1, Proj1>,
|
|
|
+ projected<InputIterator2, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<InputIterator2, Proj2>,
|
|
|
+ projected<InputIterator1, Proj1>>>
|
|
|
+constexpr auto set_symmetric_difference(InputIterator1 first1,
|
|
|
+ InputIterator1 last1,
|
|
|
+ InputIterator2 first2,
|
|
|
+ InputIterator2 last2,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ // Needs to opt-in to all permutations, since std::set_symmetric_difference
|
|
|
+ // expects comp(proj1(lhs), proj2(rhs)) and comp(proj2(lhs), proj1(rhs)) to
|
|
|
+ // compile.
|
|
|
+ return std::set_symmetric_difference(
|
|
|
+ first1, last1, first2, last2, result,
|
|
|
+ internal::PermutedProjectedBinaryPredicate(comp, proj1, proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: The ranges `range1` and `range2` are sorted with respect to
|
|
|
+// `comp` and `proj1` or `proj2`, respectively. The resulting range does not
|
|
|
+// overlap with either of the original ranges.
|
|
|
+//
|
|
|
+// Effects: Copies the elements of `range1` that are not present in `range2`,
|
|
|
+// and the elements of `range2` that are not present in `range1` to the range
|
|
|
+// beginning at `result`. The elements in the constructed range are sorted.
|
|
|
+//
|
|
|
+// Returns: The end of the constructed range.
|
|
|
+//
|
|
|
+// Complexity: At most `2 * (size(range1) + size(range2)) - 1` comparisons and
|
|
|
+// applications of each projection.
|
|
|
+//
|
|
|
+// Remarks: Stable. If `range1` contains `m` elements that are equivalent to
|
|
|
+// each other and `range2` contains `n` elements that are equivalent to them,
|
|
|
+// then `|m - n|` of those elements shall be copied to the output range: the
|
|
|
+// last `m - n` of these elements from `range1` if `m > n`, and the last `n - m`
|
|
|
+// of these elements from `range2` if `m < n`. In either case, the elements are
|
|
|
+// copied in order.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/set.symmetric.difference#:~:text=set_symmetric_difference(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename OutputIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = internal::iterator_category_t<OutputIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range2>, Proj2>,
|
|
|
+ projected<iterator_t<Range1>, Proj1>>>
|
|
|
+constexpr auto set_symmetric_difference(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ OutputIterator result,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::set_symmetric_difference(
|
|
|
+ ranges::begin(range1), ranges::end(range1), ranges::begin(range2),
|
|
|
+ ranges::end(range2), result, std::move(comp), std::move(proj1),
|
|
|
+ std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.heap.operations] Heap operations
|
|
|
+// Reference: https://wg21.link/alg.heap.operations
|
|
|
+
|
|
|
+// [push.heap] push_heap
|
|
|
+// Reference: https://wg21.link/push.heap
|
|
|
+
|
|
|
+// Preconditions: The range `[first, last - 1)` is a valid heap with respect to
|
|
|
+// `comp` and `proj`.
|
|
|
+//
|
|
|
+// Effects: Places the value in the location `last - 1` into the resulting heap
|
|
|
+// `[first, last)`.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: At most `log(last - first)` comparisons and twice as many
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/push.heap#:~:text=ranges::push_heap(I
|
|
|
+template <typename RandomAccessIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<RandomAccessIterator, Proj>,
|
|
|
+ projected<RandomAccessIterator, Proj>>>
|
|
|
+constexpr auto push_heap(RandomAccessIterator first,
|
|
|
+ RandomAccessIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ std::push_heap(first, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: The range `[begin(range), end(range) - 1)` is a valid heap
|
|
|
+// with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Effects: Places the value in the location `end(range) - 1` into the resulting
|
|
|
+// heap `range`.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: At most `log(size(range))` comparisons and twice as many
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/push.heap#:~:text=ranges::push_heap(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto push_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::push_heap(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [pop.heap] pop_heap
|
|
|
+// Reference: https://wg21.link/pop.heap
|
|
|
+
|
|
|
+// Preconditions: The range `[first, last)` is a valid non-empty heap with
|
|
|
+// respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Effects: Swaps the value in the location `first` with the value in the
|
|
|
+// location `last - 1` and makes `[first, last - 1)` into a heap with respect to
|
|
|
+// `comp` and `proj`.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: At most `2 log(last - first)` comparisons and twice as many
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/pop.heap#:~:text=ranges::pop_heap(I
|
|
|
+template <typename RandomAccessIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<RandomAccessIterator, Proj>,
|
|
|
+ projected<RandomAccessIterator, Proj>>>
|
|
|
+constexpr auto pop_heap(RandomAccessIterator first,
|
|
|
+ RandomAccessIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ std::pop_heap(first, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `range` is a valid non-empty heap with respect to `comp` and
|
|
|
+// `proj`.
|
|
|
+//
|
|
|
+// Effects: Swaps the value in the location `begin(range)` with the value in the
|
|
|
+// location `end(range) - 1` and makes `[begin(range), end(range) - 1)` into a
|
|
|
+// heap with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: At most `2 log(size(range))` comparisons and twice as many
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/pop.heap#:~:text=ranges::pop_heap(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto pop_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::pop_heap(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [make.heap] make_heap
|
|
|
+// Reference: https://wg21.link/make.heap
|
|
|
+
|
|
|
+// Effects: Constructs a heap with respect to `comp` and `proj` out of the range
|
|
|
+// `[first, last)`.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: At most `3 log(last - first)` comparisons and twice as many
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/make.heap#:~:text=ranges::make_heap(I
|
|
|
+template <typename RandomAccessIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<RandomAccessIterator, Proj>,
|
|
|
+ projected<RandomAccessIterator, Proj>>>
|
|
|
+constexpr auto make_heap(RandomAccessIterator first,
|
|
|
+ RandomAccessIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ std::make_heap(first, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Effects: Constructs a heap with respect to `comp` and `proj` out of `range`.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: At most `3 log(size(range))` comparisons and twice as many
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/make.heap#:~:text=ranges::make_heap(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto make_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::make_heap(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [sort.heap] sort_heap
|
|
|
+// Reference: https://wg21.link/sort.heap
|
|
|
+
|
|
|
+// Preconditions: The range `[first, last)` is a valid heap with respect to
|
|
|
+// `comp` and `proj`.
|
|
|
+//
|
|
|
+// Effects: Sorts elements in the heap `[first, last)` with respect to `comp`
|
|
|
+// and `proj`.
|
|
|
+//
|
|
|
+// Returns: `last`.
|
|
|
+//
|
|
|
+// Complexity: At most `2 N log N` comparisons, where `N = last - first`, and
|
|
|
+// twice as many projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/sort.heap#:~:text=ranges::sort_heap(I
|
|
|
+template <typename RandomAccessIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<RandomAccessIterator, Proj>,
|
|
|
+ projected<RandomAccessIterator, Proj>>>
|
|
|
+constexpr auto sort_heap(RandomAccessIterator first,
|
|
|
+ RandomAccessIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ std::sort_heap(first, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+ return last;
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `range` is a valid heap with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Effects: Sorts elements in the heap `range` with respect to `comp` and
|
|
|
+// `proj`.
|
|
|
+//
|
|
|
+// Returns: `end(range)`.
|
|
|
+//
|
|
|
+// Complexity: At most `2 N log N` comparisons, where `N = size(range)`, and
|
|
|
+// twice as many projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/sort.heap#:~:text=ranges::sort_heap(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto sort_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::sort_heap(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [is.heap] is_heap
|
|
|
+// Reference: https://wg21.link/is.heap
|
|
|
+
|
|
|
+// Returns: Whether the range `[first, last)` is a heap with respect to `comp`
|
|
|
+// and `proj`.
|
|
|
+//
|
|
|
+// Complexity: Linear.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap(I
|
|
|
+template <typename RandomAccessIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<RandomAccessIterator, Proj>,
|
|
|
+ projected<RandomAccessIterator, Proj>>>
|
|
|
+constexpr auto is_heap(RandomAccessIterator first,
|
|
|
+ RandomAccessIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::is_heap(first, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: Whether `range` is a heap with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Complexity: Linear.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto is_heap(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::is_heap(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: The last iterator `i` in `[first, last]` for which the range
|
|
|
+// `[first, i)` is a heap with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Complexity: Linear.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap_until(I
|
|
|
+template <typename RandomAccessIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<RandomAccessIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<RandomAccessIterator, Proj>,
|
|
|
+ projected<RandomAccessIterator, Proj>>>
|
|
|
+constexpr auto is_heap_until(RandomAccessIterator first,
|
|
|
+ RandomAccessIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::is_heap_until(
|
|
|
+ first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: The last iterator `i` in `[begin(range), end(range)]` for which the
|
|
|
+// range `[begin(range), i)` is a heap with respect to `comp` and `proj`.
|
|
|
+//
|
|
|
+// Complexity: Linear.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/is.heap#:~:text=ranges::is_heap_until(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto is_heap_until(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::is_heap_until(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.min.max] Minimum and maximum
|
|
|
+// Reference: https://wg21.link/alg.min.max
|
|
|
+
|
|
|
+// Returns: The smaller value. Returns the first argument when the arguments are
|
|
|
+// equivalent.
|
|
|
+//
|
|
|
+// Complexity: Exactly one comparison and two applications of the projection, if
|
|
|
+// any.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::min
|
|
|
+template <typename T, typename Comp = ranges::less, typename Proj = identity>
|
|
|
+constexpr const T& min(const T& a, const T& b, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return base::invoke(comp, base::invoke(proj, b), base::invoke(proj, a)) ? b
|
|
|
+ : a;
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `!empty(ilist)`.
|
|
|
+//
|
|
|
+// Returns: The smallest value in the input range. Returns a copy of the
|
|
|
+// leftmost element when several elements are equivalent to the smallest.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(ilist) - 1` comparisons and twice as many
|
|
|
+// applications of the projection, if any.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::min(initializer_list
|
|
|
+template <typename T, typename Comp = ranges::less, typename Proj = identity>
|
|
|
+constexpr T min(std::initializer_list<T> ilist,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return *std::min_element(
|
|
|
+ ilist.begin(), ilist.end(),
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `!empty(range)`.
|
|
|
+//
|
|
|
+// Returns: The smallest value in the input range. Returns a copy of the
|
|
|
+// leftmost element when several elements are equivalent to the smallest.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range) - 1` comparisons and twice as many
|
|
|
+// applications of the projection, if any.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::min(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto min(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return *std::min_element(
|
|
|
+ ranges::begin(range), ranges::end(range),
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: The larger value. Returns the first argument when the arguments are
|
|
|
+// equivalent.
|
|
|
+//
|
|
|
+// Complexity: Exactly one comparison and two applications of the projection, if
|
|
|
+// any.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::max
|
|
|
+template <typename T, typename Comp = ranges::less, typename Proj = identity>
|
|
|
+constexpr const T& max(const T& a, const T& b, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return base::invoke(comp, base::invoke(proj, a), base::invoke(proj, b)) ? b
|
|
|
+ : a;
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `!empty(ilist)`.
|
|
|
+//
|
|
|
+// Returns: The largest value in the input range. Returns a copy of the leftmost
|
|
|
+// element when several elements are equivalent to the largest.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(ilist) - 1` comparisons and twice as many
|
|
|
+// applications of the projection, if any.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::max(initializer_list
|
|
|
+template <typename T, typename Comp = ranges::less, typename Proj = identity>
|
|
|
+constexpr T max(std::initializer_list<T> ilist,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return *std::max_element(
|
|
|
+ ilist.begin(), ilist.end(),
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `!empty(range)`.
|
|
|
+//
|
|
|
+// Returns: The largest value in the input range. Returns a copy of the leftmost
|
|
|
+// element when several elements are equivalent to the smallest.
|
|
|
+//
|
|
|
+// Complexity: Exactly `size(range) - 1` comparisons and twice as many
|
|
|
+// applications of the projection, if any.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::max(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto max(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return *std::max_element(
|
|
|
+ ranges::begin(range), ranges::end(range),
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: `{b, a}` if `b` is smaller than `a`, and `{a, b}` otherwise.
|
|
|
+//
|
|
|
+// Complexity: Exactly one comparison and two applications of the projection, if
|
|
|
+// any.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::minmax
|
|
|
+template <typename T, typename Comp = ranges::less, typename Proj = identity>
|
|
|
+constexpr auto minmax(const T& a, const T& b, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return std::minmax(a, b,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `!empty(ilist)`.
|
|
|
+//
|
|
|
+// Returns: Let `X` be the return type. Returns `X{x, y}`, where `x` is a copy
|
|
|
+// of the leftmost element with the smallest value and `y` a copy of the
|
|
|
+// rightmost element with the largest value in the input range.
|
|
|
+//
|
|
|
+// Complexity: At most `(3/2) size(ilist)` applications of the corresponding
|
|
|
+// predicate and twice as many applications of the projection, if any.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.min.max#:~:text=ranges::minmax(initializer_list
|
|
|
+template <typename T, typename Comp = ranges::less, typename Proj = identity>
|
|
|
+constexpr auto minmax(std::initializer_list<T> ilist,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ auto it =
|
|
|
+ std::minmax_element(ranges::begin(ilist), ranges::end(ilist),
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+ return std::pair<T, T>{*it.first, *it.second};
|
|
|
+}
|
|
|
+
|
|
|
+// Preconditions: `!empty(range)`.
|
|
|
+//
|
|
|
+// Returns: Let `X` be the return type. Returns `X{x, y}`, where `x` is a copy
|
|
|
+// of the leftmost element with the smallest value and `y` a copy of the
|
|
|
+// rightmost element with the largest value in the input range.
|
|
|
+//
|
|
|
+// Complexity: At most `(3/2) size(range)` applications of the corresponding
|
|
|
+// predicate and twice as many applications of the projection, if any.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::minmax(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>>
|
|
|
+constexpr auto minmax(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ using T = range_value_t<Range>;
|
|
|
+ auto it =
|
|
|
+ std::minmax_element(ranges::begin(range), ranges::end(range),
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+ return std::pair<T, T>{*it.first, *it.second};
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: The first iterator i in the range `[first, last)` such that for
|
|
|
+// every iterator `j` in the range `[first, last)`,
|
|
|
+// `bool(invoke(comp, invoke(proj, *j), invoke(proj, *i)))` is `false`. Returns
|
|
|
+// `last` if `first == last`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `max(last - first - 1, 0)` comparisons and twice as
|
|
|
+// many projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::min_element(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<ForwardIterator, Proj>,
|
|
|
+ projected<ForwardIterator, Proj>>>
|
|
|
+constexpr auto min_element(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::min_element(first, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: The first iterator i in `range` such that for every iterator `j` in
|
|
|
+// `range`, `bool(invoke(comp, invoke(proj, *j), invoke(proj, *i)))` is `false`.
|
|
|
+// Returns `end(range)` if `empty(range)`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `max(size(range) - 1, 0)` comparisons and twice as many
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::min_element(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto min_element(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::min_element(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: The first iterator i in the range `[first, last)` such that for
|
|
|
+// every iterator `j` in the range `[first, last)`,
|
|
|
+// `bool(invoke(comp, invoke(proj, *i), invoke(proj, *j)))` is `false`.
|
|
|
+// Returns `last` if `first == last`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `max(last - first - 1, 0)` comparisons and twice as
|
|
|
+// many projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::max_element(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<ForwardIterator, Proj>,
|
|
|
+ projected<ForwardIterator, Proj>>>
|
|
|
+constexpr auto max_element(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::max_element(first, last,
|
|
|
+ internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: The first iterator i in `range` such that for every iterator `j`
|
|
|
+// in `range`, `bool(invoke(comp, invoke(proj, *j), invoke(proj, *j)))` is
|
|
|
+// `false`. Returns `end(range)` if `empty(range)`.
|
|
|
+//
|
|
|
+// Complexity: Exactly `max(size(range) - 1, 0)` comparisons and twice as many
|
|
|
+// projections.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::max_element(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto max_element(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::max_element(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: `{first, first}` if `[first, last)` is empty, otherwise `{m, M}`,
|
|
|
+// where `m` is the first iterator in `[first, last)` such that no iterator in
|
|
|
+// the range refers to a smaller element, and where `M` is the last iterator
|
|
|
+// in
|
|
|
+// `[first, last)` such that no iterator in the range refers to a larger
|
|
|
+// element.
|
|
|
+//
|
|
|
+// Complexity: Let `N` be `last - first`. At most `max(3/2 (N − 1), 0)`
|
|
|
+// comparisons and twice as many applications of the projection, if any.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::minmax_element(I
|
|
|
+template <typename ForwardIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<ForwardIterator, Proj>,
|
|
|
+ projected<ForwardIterator, Proj>>>
|
|
|
+constexpr auto minmax_element(ForwardIterator first,
|
|
|
+ ForwardIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::minmax_element(
|
|
|
+ first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: `{begin(range), begin(range)}` if `range` is empty, otherwise
|
|
|
+// `{m, M}`, where `m` is the first iterator in `range` such that no iterator
|
|
|
+// in the range refers to a smaller element, and where `M` is the last
|
|
|
+// iterator in `range` such that no iterator in the range refers to a larger
|
|
|
+// element.
|
|
|
+//
|
|
|
+// Complexity: Let `N` be `size(range)`. At most `max(3/2 (N − 1), 0)`
|
|
|
+// comparisons and twice as many applications of the projection, if any.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.min.max#:~:text=ranges::minmax_element(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto minmax_element(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::minmax_element(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.clamp] Bounded value
|
|
|
+// Reference: https://wg21.link/alg.clamp
|
|
|
+
|
|
|
+// Preconditions: `bool(invoke(comp, invoke(proj, hi), invoke(proj, lo)))` is
|
|
|
+// `false`.
|
|
|
+//
|
|
|
+// Returns: `lo` if `bool(invoke(comp, invoke(proj, v), invoke(proj, lo)))` is
|
|
|
+// `true`, `hi` if `bool(invoke(comp, invoke(proj, hi), invoke(proj, v)))` is
|
|
|
+// `true`, otherwise `v`.
|
|
|
+//
|
|
|
+// Complexity: At most two comparisons and three applications of the
|
|
|
+// projection.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/alg.clamp#:~:text=ranges::clamp
|
|
|
+template <typename T, typename Comp = ranges::less, typename Proj = identity>
|
|
|
+constexpr const T& clamp(const T& v,
|
|
|
+ const T& lo,
|
|
|
+ const T& hi,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ auto&& projected_v = base::invoke(proj, v);
|
|
|
+ if (base::invoke(comp, projected_v, base::invoke(proj, lo)))
|
|
|
+ return lo;
|
|
|
+
|
|
|
+ return base::invoke(comp, base::invoke(proj, hi), projected_v) ? hi : v;
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.lex.comparison] Lexicographical comparison
|
|
|
+// Reference: https://wg21.link/alg.lex.comparison
|
|
|
+
|
|
|
+// Returns: `true` if and only if the sequence of elements defined by the range
|
|
|
+// `[first1, last1)` is lexicographically less than the sequence of elements
|
|
|
+// defined by the range `[first2, last2)`.
|
|
|
+//
|
|
|
+// Complexity: At most `2 min(last1 - first1, last2 - first2)` applications of
|
|
|
+// the corresponding comparison and each projection, if any.
|
|
|
+//
|
|
|
+// Remarks: If two sequences have the same number of elements and their
|
|
|
+// corresponding elements (if any) are equivalent, then neither sequence is
|
|
|
+// lexicographically less than the other. If one sequence is a proper prefix of
|
|
|
+// the other, then the shorter sequence is lexicographically less than the
|
|
|
+// longer sequence. Otherwise, the lexicographical comparison of the sequences
|
|
|
+// yields the same result as the comparison of the first corresponding pair of
|
|
|
+// elements that are not equivalent.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.lex.comparison#:~:text=lexicographical_compare(I1
|
|
|
+template <typename ForwardIterator1,
|
|
|
+ typename ForwardIterator2,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator1>,
|
|
|
+ typename = internal::iterator_category_t<ForwardIterator2>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<ForwardIterator1, Proj1>,
|
|
|
+ projected<ForwardIterator2, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<ForwardIterator2, Proj2>,
|
|
|
+ projected<ForwardIterator1, Proj1>>>
|
|
|
+constexpr bool lexicographical_compare(ForwardIterator1 first1,
|
|
|
+ ForwardIterator1 last1,
|
|
|
+ ForwardIterator2 first2,
|
|
|
+ ForwardIterator2 last2,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
|
|
|
+ auto&& projected_first1 = base::invoke(proj1, *first1);
|
|
|
+ auto&& projected_first2 = base::invoke(proj2, *first2);
|
|
|
+ if (base::invoke(comp, projected_first1, projected_first2))
|
|
|
+ return true;
|
|
|
+ if (base::invoke(comp, projected_first2, projected_first1))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // `first2 != last2` is equivalent to `first1 == last1 && first2 != last2`
|
|
|
+ // here, since we broke out of the loop above.
|
|
|
+ return first2 != last2;
|
|
|
+}
|
|
|
+
|
|
|
+// Returns: `true` if and only if the sequence of elements defined by `range1`
|
|
|
+// is lexicographically less than the sequence of elements defined by `range2`.
|
|
|
+//
|
|
|
+// Complexity: At most `2 min(size(range1), size(range2))` applications of the
|
|
|
+// corresponding comparison and each projection, if any.
|
|
|
+//
|
|
|
+// Remarks: If two sequences have the same number of elements and their
|
|
|
+// corresponding elements (if any) are equivalent, then neither sequence is
|
|
|
+// lexicographically less than the other. If one sequence is a proper prefix of
|
|
|
+// the other, then the shorter sequence is lexicographically less than the
|
|
|
+// longer sequence. Otherwise, the lexicographical comparison of the sequences
|
|
|
+// yields the same result as the comparison of the first corresponding pair of
|
|
|
+// elements that are not equivalent.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.lex.comparison#:~:text=lexicographical_compare(R1
|
|
|
+template <typename Range1,
|
|
|
+ typename Range2,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj1 = identity,
|
|
|
+ typename Proj2 = identity,
|
|
|
+ typename = internal::range_category_t<Range1>,
|
|
|
+ typename = internal::range_category_t<Range2>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range1>, Proj1>,
|
|
|
+ projected<iterator_t<Range2>, Proj2>>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range2>, Proj2>,
|
|
|
+ projected<iterator_t<Range1>, Proj1>>>
|
|
|
+constexpr bool lexicographical_compare(Range1&& range1,
|
|
|
+ Range2&& range2,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj1 proj1 = {},
|
|
|
+ Proj2 proj2 = {}) {
|
|
|
+ return ranges::lexicographical_compare(
|
|
|
+ ranges::begin(range1), ranges::end(range1), ranges::begin(range2),
|
|
|
+ ranges::end(range2), std::move(comp), std::move(proj1), std::move(proj2));
|
|
|
+}
|
|
|
+
|
|
|
+// [alg.permutation.generators] Permutation generators
|
|
|
+// Reference: https://wg21.link/alg.permutation.generators
|
|
|
+
|
|
|
+// Effects: Takes a sequence defined by the range `[first, last)` and transforms
|
|
|
+// it into the next permutation. The next permutation is found by assuming that
|
|
|
+// the set of all permutations is lexicographically sorted with respect to
|
|
|
+// `comp` and `proj`. If no such permutation exists, transforms the sequence
|
|
|
+// into the first permutation; that is, the ascendingly-sorted one.
|
|
|
+//
|
|
|
+// Returns: `true` if a next permutation was found and otherwise `false`.
|
|
|
+//
|
|
|
+// Complexity: At most `(last - first) / 2` swaps.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.permutation.generators#:~:text=next_permutation(I
|
|
|
+template <typename BidirectionalIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<BidirectionalIterator, Proj>,
|
|
|
+ projected<BidirectionalIterator, Proj>>>
|
|
|
+constexpr auto next_permutation(BidirectionalIterator first,
|
|
|
+ BidirectionalIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::next_permutation(
|
|
|
+ first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Effects: Takes a sequence defined by `range` and transforms it into the next
|
|
|
+// permutation. The next permutation is found by assuming that the set of all
|
|
|
+// permutations is lexicographically sorted with respect to `comp` and `proj`.
|
|
|
+// If no such permutation exists, transforms the sequence into the first
|
|
|
+// permutation; that is, the ascendingly-sorted one.
|
|
|
+//
|
|
|
+// Returns: `true` if a next permutation was found and otherwise `false`.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range) / 2` swaps.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.permutation.generators#:~:text=next_permutation(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto next_permutation(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::next_permutation(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Effects: Takes a sequence defined by the range `[first, last)` and transforms
|
|
|
+// it into the previous permutation. The previous permutation is found by
|
|
|
+// assuming that the set of all permutations is lexicographically sorted with
|
|
|
+// respect to `comp` and `proj`. If no such permutation exists, transforms the
|
|
|
+// sequence into the last permutation; that is, the decreasingly-sorted one.
|
|
|
+//
|
|
|
+// Returns: `true` if a next permutation was found and otherwise `false`.
|
|
|
+//
|
|
|
+// Complexity: At most `(last - first) / 2` swaps.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.permutation.generators#:~:text=prev_permutation(I
|
|
|
+template <typename BidirectionalIterator,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::iterator_category_t<BidirectionalIterator>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<BidirectionalIterator, Proj>,
|
|
|
+ projected<BidirectionalIterator, Proj>>>
|
|
|
+constexpr auto prev_permutation(BidirectionalIterator first,
|
|
|
+ BidirectionalIterator last,
|
|
|
+ Comp comp = {},
|
|
|
+ Proj proj = {}) {
|
|
|
+ return std::prev_permutation(
|
|
|
+ first, last, internal::ProjectedBinaryPredicate(comp, proj, proj));
|
|
|
+}
|
|
|
+
|
|
|
+// Effects: Takes a sequence defined by `range` and transforms it into the
|
|
|
+// previous permutation. The previous permutation is found by assuming that the
|
|
|
+// set of all permutations is lexicographically sorted with respect to `comp`
|
|
|
+// and `proj`. If no such permutation exists, transforms the sequence into the
|
|
|
+// last permutation; that is, the decreasingly-sorted one.
|
|
|
+//
|
|
|
+// Returns: `true` if a previous permutation was found and otherwise `false`.
|
|
|
+//
|
|
|
+// Complexity: At most `size(range) / 2` swaps.
|
|
|
+//
|
|
|
+// Reference:
|
|
|
+// https://wg21.link/alg.permutation.generators#:~:text=prev_permutation(R
|
|
|
+template <typename Range,
|
|
|
+ typename Comp = ranges::less,
|
|
|
+ typename Proj = identity,
|
|
|
+ typename = internal::range_category_t<Range>,
|
|
|
+ typename = indirect_result_t<Comp&,
|
|
|
+ projected<iterator_t<Range>, Proj>,
|
|
|
+ projected<iterator_t<Range>, Proj>>>
|
|
|
+constexpr auto prev_permutation(Range&& range, Comp comp = {}, Proj proj = {}) {
|
|
|
+ return ranges::prev_permutation(ranges::begin(range), ranges::end(range),
|
|
|
+ std::move(comp), std::move(proj));
|
|
|
+}
|
|
|
+
|
|
|
+} // namespace ranges
|
|
|
+
|
|
|
+} // namespace base
|
|
|
+
|
|
|
+#endif // BASE_RANGES_ALGORITHM_H_
|
|
|
diff -up chromium-86.0.4240.111/base/ranges/functional.h.a61fb57e chromium-86.0.4240.111/base/ranges/functional.h
|
|
|
--- chromium-86.0.4240.111/base/ranges/functional.h.a61fb57e 2020-10-21 17:45:04.573057952 -0400
|
|
|
+++ chromium-86.0.4240.111/base/ranges/functional.h 2020-10-21 17:44:05.320578383 -0400
|
|
|
@@ -0,0 +1,32 @@
|
|
|
+// Copyright 2020 The Chromium Authors. All rights reserved.
|
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
|
+// found in the LICENSE file.
|
|
|
+
|
|
|
+#ifndef BASE_RANGES_FUNCTIONAL_H_
|
|
|
+#define BASE_RANGES_FUNCTIONAL_H_
|
|
|
+
|
|
|
+#include <functional>
|
|
|
+#include <type_traits>
|
|
|
+#include <utility>
|
|
|
+
|
|
|
+namespace base {
|
|
|
+
|
|
|
+namespace ranges {
|
|
|
+
|
|
|
+// Simplified implementations of C++20's std::ranges comparison function
|
|
|
+// objects. As opposed to the std::ranges implementation, these versions do not
|
|
|
+// constrain the passed-in types.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/range.cmp
|
|
|
+using equal_to = std::equal_to<>;
|
|
|
+using not_equal_to = std::not_equal_to<>;
|
|
|
+using greater = std::greater<>;
|
|
|
+using less = std::less<>;
|
|
|
+using greater_equal = std::greater_equal<>;
|
|
|
+using less_equal = std::less_equal<>;
|
|
|
+
|
|
|
+} // namespace ranges
|
|
|
+
|
|
|
+} // namespace base
|
|
|
+
|
|
|
+#endif // BASE_RANGES_FUNCTIONAL_H_
|
|
|
diff -up chromium-86.0.4240.111/base/ranges/ranges.h.a61fb57e chromium-86.0.4240.111/base/ranges/ranges.h
|
|
|
--- chromium-86.0.4240.111/base/ranges/ranges.h.a61fb57e 2020-10-21 17:45:13.828132866 -0400
|
|
|
+++ chromium-86.0.4240.111/base/ranges/ranges.h 2020-10-21 17:44:37.950842465 -0400
|
|
|
@@ -0,0 +1,140 @@
|
|
|
+// Copyright 2020 The Chromium Authors. All rights reserved.
|
|
|
+// Use of this source code is governed by a BSD-style license that can be
|
|
|
+// found in the LICENSE file.
|
|
|
+
|
|
|
+#ifndef BASE_RANGES_RANGES_H_
|
|
|
+#define BASE_RANGES_RANGES_H_
|
|
|
+
|
|
|
+#include <array>
|
|
|
+#include <iterator>
|
|
|
+#include <type_traits>
|
|
|
+#include <utility>
|
|
|
+
|
|
|
+#include "base/template_util.h"
|
|
|
+
|
|
|
+namespace base {
|
|
|
+
|
|
|
+namespace internal {
|
|
|
+
|
|
|
+// Overload for C array.
|
|
|
+template <typename T, size_t N>
|
|
|
+constexpr T* begin(T (&array)[N], priority_tag<2>) {
|
|
|
+ return array;
|
|
|
+}
|
|
|
+
|
|
|
+// Overload for mutable std::array. Required since std::array::begin is not
|
|
|
+// constexpr prior to C++17. Needs to dispatch to the const overload since only
|
|
|
+// const operator[] is constexpr in C++14.
|
|
|
+template <typename T, size_t N>
|
|
|
+constexpr T* begin(std::array<T, N>& array, priority_tag<2> tag) {
|
|
|
+ return const_cast<T*>(begin(const_cast<const std::array<T, N>&>(array), tag));
|
|
|
+}
|
|
|
+
|
|
|
+// Overload for const std::array. Required since std::array::begin is not
|
|
|
+// constexpr prior to C++17.
|
|
|
+template <typename T, size_t N>
|
|
|
+constexpr const T* begin(const std::array<T, N>& array, priority_tag<2>) {
|
|
|
+ return N != 0 ? &array[0] : nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+// Generic container overload.
|
|
|
+template <typename Range>
|
|
|
+constexpr auto begin(Range&& range, priority_tag<1>)
|
|
|
+ -> decltype(std::forward<Range>(range).begin()) {
|
|
|
+ return std::forward<Range>(range).begin();
|
|
|
+}
|
|
|
+
|
|
|
+// Overload for free begin() function.
|
|
|
+template <typename Range>
|
|
|
+constexpr auto begin(Range&& range, priority_tag<0>)
|
|
|
+ -> decltype(begin(std::forward<Range>(range))) {
|
|
|
+ return begin(std::forward<Range>(range));
|
|
|
+}
|
|
|
+
|
|
|
+// Overload for C array.
|
|
|
+template <typename T, size_t N>
|
|
|
+constexpr T* end(T (&array)[N], priority_tag<2>) {
|
|
|
+ return array + N;
|
|
|
+}
|
|
|
+
|
|
|
+// Overload for mutable std::array. Required since std::array::end is not
|
|
|
+// constexpr prior to C++17. Needs to dispatch to the const overload since only
|
|
|
+// const operator[] is constexpr in C++14.
|
|
|
+template <typename T, size_t N>
|
|
|
+constexpr T* end(std::array<T, N>& array, priority_tag<2> tag) {
|
|
|
+ return const_cast<T*>(end(const_cast<const std::array<T, N>&>(array), tag));
|
|
|
+}
|
|
|
+
|
|
|
+// Overload for const std::array. Required since std::array::end is not
|
|
|
+// constexpr prior to C++17.
|
|
|
+template <typename T, size_t N>
|
|
|
+constexpr const T* end(const std::array<T, N>& array, priority_tag<2>) {
|
|
|
+ return N != 0 ? (&array[0]) + N : nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+// Generic container overload.
|
|
|
+template <typename Range>
|
|
|
+constexpr auto end(Range&& range, priority_tag<1>)
|
|
|
+ -> decltype(std::forward<Range>(range).end()) {
|
|
|
+ return std::forward<Range>(range).end();
|
|
|
+}
|
|
|
+
|
|
|
+// Overload for free end() function.
|
|
|
+template <typename Range>
|
|
|
+constexpr auto end(Range&& range, priority_tag<0>)
|
|
|
+ -> decltype(end(std::forward<Range>(range))) {
|
|
|
+ return end(std::forward<Range>(range));
|
|
|
+}
|
|
|
+
|
|
|
+} // namespace internal
|
|
|
+
|
|
|
+namespace ranges {
|
|
|
+
|
|
|
+// Simplified implementation of C++20's std::ranges::begin.
|
|
|
+// As opposed to std::ranges::begin, this implementation does does not check
|
|
|
+// whether begin() returns an iterator and does not inhibit ADL.
|
|
|
+//
|
|
|
+// The trailing return type and dispatch to the internal implementation is
|
|
|
+// necessary to be SFINAE friendly.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/range.access.begin
|
|
|
+template <typename Range>
|
|
|
+constexpr auto begin(Range&& range) noexcept
|
|
|
+ -> decltype(internal::begin(std::forward<Range>(range),
|
|
|
+ internal::priority_tag<2>())) {
|
|
|
+ return internal::begin(std::forward<Range>(range),
|
|
|
+ internal::priority_tag<2>());
|
|
|
+}
|
|
|
+
|
|
|
+// Simplified implementation of C++20's std::ranges::end.
|
|
|
+// As opposed to std::ranges::end, this implementation does does not check
|
|
|
+// whether end() returns an iterator and does not inhibit ADL.
|
|
|
+//
|
|
|
+// The trailing return type and dispatch to the internal implementation is
|
|
|
+// necessary to be SFINAE friendly.
|
|
|
+//
|
|
|
+// Reference: - https://wg21.link/range.access.end
|
|
|
+template <typename Range>
|
|
|
+constexpr auto end(Range&& range) noexcept
|
|
|
+ -> decltype(internal::end(std::forward<Range>(range),
|
|
|
+ internal::priority_tag<2>())) {
|
|
|
+ return internal::end(std::forward<Range>(range), internal::priority_tag<2>());
|
|
|
+}
|
|
|
+
|
|
|
+// Implementation of C++20's std::ranges::iterator_t.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/ranges.syn#:~:text=iterator_t
|
|
|
+template <typename Range>
|
|
|
+using iterator_t = decltype(ranges::begin(std::declval<Range&>()));
|
|
|
+
|
|
|
+// Implementation of C++20's std::ranges::range_value_t.
|
|
|
+//
|
|
|
+// Reference: https://wg21.link/ranges.syn#:~:text=range_value_t
|
|
|
+template <typename Range>
|
|
|
+using range_value_t = iter_value_t<iterator_t<Range>>;
|
|
|
+
|
|
|
+} // namespace ranges
|
|
|
+
|
|
|
+} // namespace base
|
|
|
+
|
|
|
+#endif // BASE_RANGES_RANGES_H_
|
|
|
diff -up chromium-86.0.4240.111/base/sampling_heap_profiler/poisson_allocation_sampler.cc.a61fb57e chromium-86.0.4240.111/base/sampling_heap_profiler/poisson_allocation_sampler.cc
|
|
|
--- chromium-86.0.4240.111/base/sampling_heap_profiler/poisson_allocation_sampler.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/sampling_heap_profiler/poisson_allocation_sampler.cc 2020-10-21 17:11:20.011228811 -0400
|
|
|
@@ -4,7 +4,6 @@
|
|
|
|
|
|
#include "base/sampling_heap_profiler/poisson_allocation_sampler.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <atomic>
|
|
|
#include <cmath>
|
|
|
#include <memory>
|
|
|
@@ -17,6 +16,7 @@
|
|
|
#include "base/no_destructor.h"
|
|
|
#include "base/partition_alloc_buildflags.h"
|
|
|
#include "base/rand_util.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "build/build_config.h"
|
|
|
|
|
|
#if defined(OS_APPLE) || defined(OS_ANDROID)
|
|
|
@@ -557,8 +557,7 @@ void PoissonAllocationSampler::SuppressR
|
|
|
void PoissonAllocationSampler::AddSamplesObserver(SamplesObserver* observer) {
|
|
|
ScopedMuteThreadSamples no_reentrancy_scope;
|
|
|
AutoLock lock(mutex_);
|
|
|
- DCHECK(std::find(observers_.begin(), observers_.end(), observer) ==
|
|
|
- observers_.end());
|
|
|
+ DCHECK(ranges::find(observers_, observer) == observers_.end());
|
|
|
observers_.push_back(observer);
|
|
|
InstallAllocatorHooksOnce();
|
|
|
g_running = !observers_.empty();
|
|
|
@@ -568,7 +567,7 @@ void PoissonAllocationSampler::RemoveSam
|
|
|
SamplesObserver* observer) {
|
|
|
ScopedMuteThreadSamples no_reentrancy_scope;
|
|
|
AutoLock lock(mutex_);
|
|
|
- auto it = std::find(observers_.begin(), observers_.end(), observer);
|
|
|
+ auto it = ranges::find(observers_, observer);
|
|
|
DCHECK(it != observers_.end());
|
|
|
observers_.erase(it);
|
|
|
g_running = !observers_.empty();
|
|
|
diff -up chromium-86.0.4240.111/base/scoped_observer.h.a61fb57e chromium-86.0.4240.111/base/scoped_observer.h
|
|
|
--- chromium-86.0.4240.111/base/scoped_observer.h.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/scoped_observer.h 2020-10-21 17:11:20.011228811 -0400
|
|
|
@@ -7,11 +7,11 @@
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <vector>
|
|
|
|
|
|
#include "base/check.h"
|
|
|
#include "base/macros.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
|
|
|
// ScopedObserver is used to keep track of the set of sources an object has
|
|
|
@@ -56,7 +56,7 @@ class ScopedObserver {
|
|
|
|
|
|
// Remove the object passed to the constructor as an observer from |source|.
|
|
|
void Remove(Source* source) {
|
|
|
- auto it = std::find(sources_.begin(), sources_.end(), source);
|
|
|
+ auto it = base::ranges::find(sources_, source);
|
|
|
DCHECK(it != sources_.end());
|
|
|
sources_.erase(it);
|
|
|
(source->*RemoveObsFn)(observer_);
|
|
|
diff -up chromium-86.0.4240.111/base/strings/abseil_string_conversions.cc.a61fb57e chromium-86.0.4240.111/base/strings/abseil_string_conversions.cc
|
|
|
--- chromium-86.0.4240.111/base/strings/abseil_string_conversions.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/strings/abseil_string_conversions.cc 2020-10-21 17:11:20.012228820 -0400
|
|
|
@@ -4,10 +4,10 @@
|
|
|
|
|
|
#include "base/strings/abseil_string_conversions.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <vector>
|
|
|
|
|
|
#include "base/containers/span.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/strings/string_piece.h"
|
|
|
#include "third_party/abseil-cpp/absl/strings/string_view.h"
|
|
|
|
|
|
@@ -16,16 +16,14 @@ namespace base {
|
|
|
std::vector<absl::string_view> StringPiecesToStringViews(
|
|
|
span<const StringPiece> pieces) {
|
|
|
std::vector<absl::string_view> views(pieces.size());
|
|
|
- std::transform(pieces.begin(), pieces.end(), views.begin(),
|
|
|
- &StringPieceToStringView);
|
|
|
+ ranges::transform(pieces, views.begin(), &StringPieceToStringView);
|
|
|
return views;
|
|
|
}
|
|
|
|
|
|
std::vector<StringPiece> StringViewsToStringPieces(
|
|
|
span<const absl::string_view> views) {
|
|
|
std::vector<StringPiece> pieces(views.size());
|
|
|
- std::transform(views.begin(), views.end(), pieces.begin(),
|
|
|
- &StringViewToStringPiece);
|
|
|
+ ranges::transform(views, pieces.begin(), &StringViewToStringPiece);
|
|
|
return pieces;
|
|
|
}
|
|
|
|
|
|
diff -up chromium-86.0.4240.111/base/strings/string_util_internal.h.a61fb57e chromium-86.0.4240.111/base/strings/string_util_internal.h
|
|
|
--- chromium-86.0.4240.111/base/strings/string_util_internal.h.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/strings/string_util_internal.h 2020-10-21 17:11:20.012228820 -0400
|
|
|
@@ -7,6 +7,7 @@
|
|
|
|
|
|
#include "base/logging.h"
|
|
|
#include "base/notreached.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/strings/string_piece.h"
|
|
|
#include "base/third_party/icu/icu_utf.h"
|
|
|
|
|
|
@@ -578,8 +579,7 @@ StringType DoReplaceStringPlaceholders(
|
|
|
ReplacementOffset r_offset(index,
|
|
|
static_cast<int>(formatted.size()));
|
|
|
r_offsets.insert(
|
|
|
- std::upper_bound(r_offsets.begin(), r_offsets.end(), r_offset,
|
|
|
- &CompareParameter),
|
|
|
+ ranges::upper_bound(r_offsets, r_offset, &CompareParameter),
|
|
|
r_offset);
|
|
|
}
|
|
|
if (index < substitutions)
|
|
|
diff -up chromium-86.0.4240.111/base/synchronization/waitable_event_posix.cc.a61fb57e chromium-86.0.4240.111/base/synchronization/waitable_event_posix.cc
|
|
|
--- chromium-86.0.4240.111/base/synchronization/waitable_event_posix.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/synchronization/waitable_event_posix.cc 2020-10-21 17:11:20.012228820 -0400
|
|
|
@@ -4,13 +4,13 @@
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <limits>
|
|
|
#include <vector>
|
|
|
|
|
|
#include "base/check_op.h"
|
|
|
#include "base/debug/activity_tracker.h"
|
|
|
#include "base/optional.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/synchronization/condition_variable.h"
|
|
|
#include "base/synchronization/lock.h"
|
|
|
#include "base/synchronization/waitable_event.h"
|
|
|
@@ -265,7 +265,7 @@ size_t WaitableEvent::WaitMany(WaitableE
|
|
|
|
|
|
DCHECK_EQ(count, waitables.size());
|
|
|
|
|
|
- sort(waitables.begin(), waitables.end(), cmp_fst_addr);
|
|
|
+ ranges::sort(waitables, cmp_fst_addr);
|
|
|
|
|
|
// The set of waitables must be distinct. Since we have just sorted by
|
|
|
// address, we can check this cheaply by comparing pairs of consecutive
|
|
|
diff -up chromium-86.0.4240.111/base/task/common/checked_lock_impl.cc.a61fb57e chromium-86.0.4240.111/base/task/common/checked_lock_impl.cc
|
|
|
--- chromium-86.0.4240.111/base/task/common/checked_lock_impl.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/task/common/checked_lock_impl.cc 2020-10-21 17:11:20.013228828 -0400
|
|
|
@@ -4,12 +4,12 @@
|
|
|
|
|
|
#include "base/task/common/checked_lock_impl.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <unordered_map>
|
|
|
#include <vector>
|
|
|
|
|
|
#include "base/check_op.h"
|
|
|
#include "base/lazy_instance.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/synchronization/condition_variable.h"
|
|
|
#include "base/task/common/checked_lock.h"
|
|
|
#include "base/threading/platform_thread.h"
|
|
|
@@ -44,8 +44,7 @@ class SafeAcquisitionTracker {
|
|
|
|
|
|
void RecordRelease(const CheckedLockImpl* const lock) {
|
|
|
LockVector* acquired_locks = GetAcquiredLocksOnCurrentThread();
|
|
|
- const auto iter_at_lock =
|
|
|
- std::find(acquired_locks->begin(), acquired_locks->end(), lock);
|
|
|
+ const auto iter_at_lock = ranges::find(*acquired_locks, lock);
|
|
|
DCHECK(iter_at_lock != acquired_locks->end());
|
|
|
acquired_locks->erase(iter_at_lock);
|
|
|
}
|
|
|
diff -up chromium-86.0.4240.111/base/task/common/operations_controller_unittest.cc.a61fb57e chromium-86.0.4240.111/base/task/common/operations_controller_unittest.cc
|
|
|
--- chromium-86.0.4240.111/base/task/common/operations_controller_unittest.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/task/common/operations_controller_unittest.cc 2020-10-21 17:11:20.013228828 -0400
|
|
|
@@ -8,6 +8,7 @@
|
|
|
#include <cstdint>
|
|
|
#include <utility>
|
|
|
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/threading/platform_thread.h"
|
|
|
#include "base/threading/simple_thread.h"
|
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
@@ -124,8 +125,7 @@ class TestThread : public SimpleThread {
|
|
|
}
|
|
|
if (!was_started)
|
|
|
continue;
|
|
|
- if (std::any_of(tokens.begin(), tokens.end(),
|
|
|
- [](const auto& token) { return !token; })) {
|
|
|
+ if (ranges::any_of(tokens, [](const auto& token) { return !token; })) {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
diff -up chromium-86.0.4240.111/base/task/common/task_annotator.cc.a61fb57e chromium-86.0.4240.111/base/task/common/task_annotator.cc
|
|
|
--- chromium-86.0.4240.111/base/task/common/task_annotator.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/task/common/task_annotator.cc 2020-10-21 17:11:20.013228828 -0400
|
|
|
@@ -9,6 +9,7 @@
|
|
|
#include "base/debug/activity_tracker.h"
|
|
|
#include "base/debug/alias.h"
|
|
|
#include "base/no_destructor.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/threading/thread_local.h"
|
|
|
#include "base/trace_event/base_tracing.h"
|
|
|
|
|
|
@@ -127,8 +128,7 @@ void TaskAnnotator::RunTask(const char*
|
|
|
task_backtrace.back() = reinterpret_cast<void*>(0x0d00d1d1d178119);
|
|
|
|
|
|
task_backtrace[1] = pending_task->posted_from.program_counter();
|
|
|
- std::copy(pending_task->task_backtrace.begin(),
|
|
|
- pending_task->task_backtrace.end(), task_backtrace.begin() + 2);
|
|
|
+ ranges::copy(pending_task->task_backtrace, task_backtrace.begin() + 2);
|
|
|
task_backtrace[kStackTaskTraceSnapshotSize - 2] =
|
|
|
reinterpret_cast<void*>(pending_task->ipc_hash);
|
|
|
debug::Alias(&task_backtrace);
|
|
|
diff -up chromium-86.0.4240.111/base/task/sequence_manager/sequence_manager_impl.cc.a61fb57e chromium-86.0.4240.111/base/task/sequence_manager/sequence_manager_impl.cc
|
|
|
--- chromium-86.0.4240.111/base/task/sequence_manager/sequence_manager_impl.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/task/sequence_manager/sequence_manager_impl.cc 2020-10-21 17:11:20.014228837 -0400
|
|
|
@@ -18,6 +18,7 @@
|
|
|
#include "base/no_destructor.h"
|
|
|
#include "base/optional.h"
|
|
|
#include "base/rand_util.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/task/sequence_manager/real_time_domain.h"
|
|
|
#include "base/task/sequence_manager/task_time_observer.h"
|
|
|
#include "base/task/sequence_manager/thread_controller_impl.h"
|
|
|
@@ -539,8 +540,7 @@ void SequenceManagerImpl::LogTaskDebugIn
|
|
|
case Settings::TaskLogging::kEnabledWithBacktrace: {
|
|
|
std::array<const void*, PendingTask::kTaskBacktraceLength + 1> task_trace;
|
|
|
task_trace[0] = task->posted_from.program_counter();
|
|
|
- std::copy(task->task_backtrace.begin(), task->task_backtrace.end(),
|
|
|
- task_trace.begin() + 1);
|
|
|
+ ranges::copy(task->task_backtrace, task_trace.begin() + 1);
|
|
|
size_t length = 0;
|
|
|
while (length < task_trace.size() && task_trace[length])
|
|
|
++length;
|
|
|
diff -up chromium-86.0.4240.111/base/task/sequence_manager/task_queue_impl.cc.a61fb57e chromium-86.0.4240.111/base/task/sequence_manager/task_queue_impl.cc
|
|
|
--- chromium-86.0.4240.111/base/task/sequence_manager/task_queue_impl.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/task/sequence_manager/task_queue_impl.cc 2020-10-21 17:11:20.014228837 -0400
|
|
|
@@ -10,6 +10,7 @@
|
|
|
#include <utility>
|
|
|
|
|
|
#include "base/logging.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/strings/stringprintf.h"
|
|
|
#include "base/task/common/scoped_defer_task_posting.h"
|
|
|
#include "base/task/sequence_manager/sequence_manager_impl.h"
|
|
|
@@ -1404,7 +1405,7 @@ void TaskQueueImpl::DelayedIncomingQueue
|
|
|
|
|
|
// If we deleted something, re-enforce the heap property.
|
|
|
if (task_deleted)
|
|
|
- std::make_heap(queue_.c.begin(), queue_.c.end(), queue_.comp);
|
|
|
+ ranges::make_heap(queue_.c, queue_.comp);
|
|
|
}
|
|
|
|
|
|
Value TaskQueueImpl::DelayedIncomingQueue::AsValue(TimeTicks now) const {
|
|
|
diff -up chromium-86.0.4240.111/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc.a61fb57e chromium-86.0.4240.111/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc
|
|
|
--- chromium-86.0.4240.111/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc 2020-10-21 17:11:20.015228846 -0400
|
|
|
@@ -4,7 +4,6 @@
|
|
|
|
|
|
#include "base/task/thread_pool/pooled_single_thread_task_runner_manager.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <memory>
|
|
|
#include <string>
|
|
|
#include <utility>
|
|
|
@@ -12,6 +11,7 @@
|
|
|
#include "base/bind.h"
|
|
|
#include "base/callback.h"
|
|
|
#include "base/memory/ptr_util.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/single_thread_task_runner.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/strings/stringprintf.h"
|
|
|
@@ -719,7 +719,7 @@ void PooledSingleThreadTaskRunnerManager
|
|
|
if (workers_.empty())
|
|
|
return;
|
|
|
|
|
|
- auto worker_iter = std::find(workers_.begin(), workers_.end(), worker);
|
|
|
+ auto worker_iter = ranges::find(workers_, worker);
|
|
|
DCHECK(worker_iter != workers_.end());
|
|
|
worker_to_destroy = std::move(*worker_iter);
|
|
|
workers_.erase(worker_iter);
|
|
|
diff -up chromium-86.0.4240.111/base/task/thread_pool/thread_group_impl.cc.a61fb57e chromium-86.0.4240.111/base/task/thread_pool/thread_group_impl.cc
|
|
|
--- chromium-86.0.4240.111/base/task/thread_pool/thread_group_impl.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/task/thread_pool/thread_group_impl.cc 2020-10-21 17:11:20.015228846 -0400
|
|
|
@@ -22,6 +22,7 @@
|
|
|
#include "base/metrics/histogram.h"
|
|
|
#include "base/numerics/clamped_math.h"
|
|
|
#include "base/optional.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/sequence_token.h"
|
|
|
#include "base/strings/string_util.h"
|
|
|
#include "base/strings/stringprintf.h"
|
|
|
@@ -83,10 +84,10 @@ constexpr TimeDelta kBackgroundBlockedWo
|
|
|
// Only used in DCHECKs.
|
|
|
bool ContainsWorker(const std::vector<scoped_refptr<WorkerThread>>& workers,
|
|
|
const WorkerThread* worker) {
|
|
|
- auto it = std::find_if(workers.begin(), workers.end(),
|
|
|
- [worker](const scoped_refptr<WorkerThread>& i) {
|
|
|
- return i.get() == worker;
|
|
|
- });
|
|
|
+ auto it =
|
|
|
+ ranges::find_if(workers, [worker](const scoped_refptr<WorkerThread>& i) {
|
|
|
+ return i.get() == worker;
|
|
|
+ });
|
|
|
return it != workers.end();
|
|
|
}
|
|
|
|
|
|
@@ -734,8 +735,7 @@ void ThreadGroupImpl::WorkerThreadDelega
|
|
|
outer_->idle_workers_stack_.Remove(worker);
|
|
|
|
|
|
// Remove the worker from |workers_|.
|
|
|
- auto worker_iter =
|
|
|
- std::find(outer_->workers_.begin(), outer_->workers_.end(), worker);
|
|
|
+ auto worker_iter = ranges::find(outer_->workers_, worker);
|
|
|
DCHECK(worker_iter != outer_->workers_.end());
|
|
|
outer_->workers_.erase(worker_iter);
|
|
|
}
|
|
|
diff -up chromium-86.0.4240.111/base/task/thread_pool/worker_thread_stack.cc.a61fb57e chromium-86.0.4240.111/base/task/thread_pool/worker_thread_stack.cc
|
|
|
--- chromium-86.0.4240.111/base/task/thread_pool/worker_thread_stack.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/task/thread_pool/worker_thread_stack.cc 2020-10-21 17:11:20.016228854 -0400
|
|
|
@@ -4,9 +4,8 @@
|
|
|
|
|
|
#include "base/task/thread_pool/worker_thread_stack.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
-
|
|
|
#include "base/check_op.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/task/thread_pool/worker_thread.h"
|
|
|
|
|
|
@@ -47,7 +46,7 @@ bool WorkerThreadStack::Contains(const W
|
|
|
void WorkerThreadStack::Remove(const WorkerThread* worker) {
|
|
|
DCHECK(!IsEmpty());
|
|
|
DCHECK_NE(worker, stack_.back());
|
|
|
- auto it = std::find(stack_.begin(), stack_.end(), worker);
|
|
|
+ auto it = ranges::find(stack_, worker);
|
|
|
DCHECK(it != stack_.end());
|
|
|
DCHECK_NE(TimeTicks(), (*it)->GetLastUsedTime());
|
|
|
stack_.erase(it);
|
|
|
diff -up chromium-86.0.4240.111/base/test/launcher/test_launcher.cc.a61fb57e chromium-86.0.4240.111/base/test/launcher/test_launcher.cc
|
|
|
--- chromium-86.0.4240.111/base/test/launcher/test_launcher.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/test/launcher/test_launcher.cc 2020-10-21 17:11:20.016228854 -0400
|
|
|
@@ -30,6 +30,7 @@
|
|
|
#include "base/numerics/safe_conversions.h"
|
|
|
#include "base/process/kill.h"
|
|
|
#include "base/process/launch.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/run_loop.h"
|
|
|
#include "base/single_thread_task_runner.h"
|
|
|
#include "base/strings/pattern.h"
|
|
|
@@ -670,7 +671,7 @@ void TestRunner::Run(const std::vector<s
|
|
|
CHECK_GT(runner_count_, 0u);
|
|
|
tests_to_run_ = test_names;
|
|
|
// Reverse test order to avoid coping the whole vector when removing tests.
|
|
|
- std::reverse(tests_to_run_.begin(), tests_to_run_.end());
|
|
|
+ ranges::reverse(tests_to_run_);
|
|
|
runners_done_ = 0;
|
|
|
task_runners_.clear();
|
|
|
for (size_t i = 0; i < runner_count_; i++) {
|
|
|
@@ -1554,7 +1555,7 @@ bool TestLauncher::ShuffleTests(CommandL
|
|
|
|
|
|
std::mt19937 randomizer;
|
|
|
randomizer.seed(shuffle_seed);
|
|
|
- std::shuffle(tests_.begin(), tests_.end(), randomizer);
|
|
|
+ ranges::shuffle(tests_, randomizer);
|
|
|
|
|
|
fprintf(stdout, "Randomizing with seed %u\n", shuffle_seed);
|
|
|
fflush(stdout);
|
|
|
diff -up chromium-86.0.4240.111/base/test/scoped_feature_list.cc.a61fb57e chromium-86.0.4240.111/base/test/scoped_feature_list.cc
|
|
|
--- chromium-86.0.4240.111/base/test/scoped_feature_list.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/test/scoped_feature_list.cc 2020-10-21 17:11:20.017228863 -0400
|
|
|
@@ -4,12 +4,12 @@
|
|
|
|
|
|
#include "base/test/scoped_feature_list.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <utility>
|
|
|
#include <vector>
|
|
|
|
|
|
#include "base/memory/ptr_util.h"
|
|
|
#include "base/metrics/field_trial_param_associator.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/strings/string_number_conversions.h"
|
|
|
#include "base/strings/string_split.h"
|
|
|
#include "base/strings/string_util.h"
|
|
|
@@ -71,10 +71,10 @@ struct Features {
|
|
|
// with GetFeatureName() and also could be without parameters.
|
|
|
bool ContainsFeature(const std::vector<StringPiece>& feature_vector,
|
|
|
StringPiece feature_name) {
|
|
|
- auto iter = std::find_if(feature_vector.begin(), feature_vector.end(),
|
|
|
- [&feature_name](const StringPiece& a) {
|
|
|
- return GetFeatureName(a) == feature_name;
|
|
|
- });
|
|
|
+ auto iter =
|
|
|
+ ranges::find_if(feature_vector, [&feature_name](const StringPiece& a) {
|
|
|
+ return GetFeatureName(a) == feature_name;
|
|
|
+ });
|
|
|
return iter != feature_vector.end();
|
|
|
}
|
|
|
|
|
|
diff -up chromium-86.0.4240.111/base/test/trace_event_analyzer.cc.a61fb57e chromium-86.0.4240.111/base/test/trace_event_analyzer.cc
|
|
|
--- chromium-86.0.4240.111/base/test/trace_event_analyzer.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/test/trace_event_analyzer.cc 2020-10-21 17:11:20.017228863 -0400
|
|
|
@@ -14,6 +14,7 @@
|
|
|
#include "base/logging.h"
|
|
|
#include "base/memory/ptr_util.h"
|
|
|
#include "base/memory/ref_counted_memory.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/run_loop.h"
|
|
|
#include "base/strings/pattern.h"
|
|
|
#include "base/trace_event/trace_buffer.h"
|
|
|
@@ -775,7 +776,7 @@ bool TraceAnalyzer::SetEvents(const std:
|
|
|
raw_events_.clear();
|
|
|
if (!ParseEventsFromJson(json_events, &raw_events_))
|
|
|
return false;
|
|
|
- std::stable_sort(raw_events_.begin(), raw_events_.end());
|
|
|
+ base::ranges::stable_sort(raw_events_);
|
|
|
ParseMetadata();
|
|
|
return true;
|
|
|
}
|
|
|
@@ -964,7 +965,7 @@ bool GetRateStats(const TraceEventVector
|
|
|
deltas.push_back(delta);
|
|
|
}
|
|
|
|
|
|
- std::sort(deltas.begin(), deltas.end());
|
|
|
+ base::ranges::sort(deltas);
|
|
|
|
|
|
if (options) {
|
|
|
if (options->trim_min + options->trim_max > events.size() - kMinEvents) {
|
|
|
@@ -980,8 +981,8 @@ bool GetRateStats(const TraceEventVector
|
|
|
for (size_t i = 0; i < num_deltas; ++i)
|
|
|
delta_sum += deltas[i];
|
|
|
|
|
|
- stats->min_us = *std::min_element(deltas.begin(), deltas.end());
|
|
|
- stats->max_us = *std::max_element(deltas.begin(), deltas.end());
|
|
|
+ stats->min_us = *base::ranges::min_element(deltas);
|
|
|
+ stats->max_us = *base::ranges::max_element(deltas);
|
|
|
stats->mean_us = delta_sum / static_cast<double>(num_deltas);
|
|
|
|
|
|
double sum_mean_offsets_squared = 0.0;
|
|
|
diff -up chromium-86.0.4240.111/base/threading/hang_watcher.cc.a61fb57e chromium-86.0.4240.111/base/threading/hang_watcher.cc
|
|
|
--- chromium-86.0.4240.111/base/threading/hang_watcher.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/threading/hang_watcher.cc 2020-10-21 17:11:20.018228872 -0400
|
|
|
@@ -4,7 +4,6 @@
|
|
|
|
|
|
#include "base/threading/hang_watcher.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <atomic>
|
|
|
#include <utility>
|
|
|
|
|
|
@@ -16,6 +15,7 @@
|
|
|
#include "base/feature_list.h"
|
|
|
#include "base/metrics/field_trial_params.h"
|
|
|
#include "base/no_destructor.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/strings/string_number_conversions.h"
|
|
|
#include "base/synchronization/lock.h"
|
|
|
#include "base/synchronization/waitable_event.h"
|
|
|
@@ -413,10 +413,10 @@ HangWatcher::WatchStateSnapShot::WatchSt
|
|
|
|
|
|
// Sort |hung_watch_state_copies_| by order of decreasing hang severity so the
|
|
|
// most severe hang is first in the list.
|
|
|
- std::sort(hung_watch_state_copies_.begin(), hung_watch_state_copies_.end(),
|
|
|
- [](const WatchStateCopy& lhs, const WatchStateCopy& rhs) {
|
|
|
- return lhs.deadline < rhs.deadline;
|
|
|
- });
|
|
|
+ ranges::sort(hung_watch_state_copies_,
|
|
|
+ [](const WatchStateCopy& lhs, const WatchStateCopy& rhs) {
|
|
|
+ return lhs.deadline < rhs.deadline;
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
HangWatcher::WatchStateSnapShot::WatchStateSnapShot(
|
|
|
@@ -476,8 +476,8 @@ void HangWatcher::Monitor() {
|
|
|
// atomically. This is fine. Detecting a hang is generally best effort and
|
|
|
// if a thread resumes from hang in the time it takes to move on to
|
|
|
// capturing then its ID will be absent from the crash keys.
|
|
|
- bool any_thread_hung = std::any_of(
|
|
|
- watch_states_.cbegin(), watch_states_.cend(),
|
|
|
+ bool any_thread_hung = ranges::any_of(
|
|
|
+ watch_states_,
|
|
|
[this, now](const std::unique_ptr<internal::HangWatchState>& state) {
|
|
|
uint64_t flags;
|
|
|
base::TimeTicks deadline;
|
|
|
@@ -595,12 +595,12 @@ void HangWatcher::UnregisterThread() {
|
|
|
internal::HangWatchState* current_hang_watch_state =
|
|
|
internal::HangWatchState::GetHangWatchStateForCurrentThread()->Get();
|
|
|
|
|
|
- auto it =
|
|
|
- std::find_if(watch_states_.cbegin(), watch_states_.cend(),
|
|
|
- [current_hang_watch_state](
|
|
|
- const std::unique_ptr<internal::HangWatchState>& state) {
|
|
|
- return state.get() == current_hang_watch_state;
|
|
|
- });
|
|
|
+ auto it = ranges::find_if(
|
|
|
+ watch_states_,
|
|
|
+ [current_hang_watch_state](
|
|
|
+ const std::unique_ptr<internal::HangWatchState>& state) {
|
|
|
+ return state.get() == current_hang_watch_state;
|
|
|
+ });
|
|
|
|
|
|
// Thread should be registered to get unregistered.
|
|
|
DCHECK(it != watch_states_.end());
|
|
|
diff -up chromium-86.0.4240.111/base/trace_event/trace_log.cc.a61fb57e chromium-86.0.4240.111/base/trace_event/trace_log.cc
|
|
|
--- chromium-86.0.4240.111/base/trace_event/trace_log.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/trace_event/trace_log.cc 2020-10-21 17:11:20.018228872 -0400
|
|
|
@@ -4,7 +4,6 @@
|
|
|
|
|
|
#include "base/trace_event/trace_log.h"
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <cmath>
|
|
|
#include <limits>
|
|
|
#include <memory>
|
|
|
@@ -23,6 +22,7 @@
|
|
|
#include "base/no_destructor.h"
|
|
|
#include "base/process/process.h"
|
|
|
#include "base/process/process_metrics.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/strings/string_piece.h"
|
|
|
#include "base/strings/string_split.h"
|
|
|
@@ -777,8 +777,7 @@ void TraceLog::AddEnabledStateObserver(E
|
|
|
void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) {
|
|
|
AutoLock lock(observers_lock_);
|
|
|
enabled_state_observers_.erase(
|
|
|
- std::remove(enabled_state_observers_.begin(),
|
|
|
- enabled_state_observers_.end(), listener),
|
|
|
+ ranges::remove(enabled_state_observers_, listener),
|
|
|
enabled_state_observers_.end());
|
|
|
}
|
|
|
|
|
|
diff -up chromium-86.0.4240.111/base/values.cc.a61fb57e chromium-86.0.4240.111/base/values.cc
|
|
|
--- chromium-86.0.4240.111/base/values.cc.a61fb57e 2020-10-20 20:14:18.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/base/values.cc 2020-10-21 17:11:20.019228880 -0400
|
|
|
@@ -6,7 +6,6 @@
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
-#include <algorithm>
|
|
|
#include <cmath>
|
|
|
#include <new>
|
|
|
#include <ostream>
|
|
|
@@ -18,6 +17,7 @@
|
|
|
#include "base/json/json_writer.h"
|
|
|
#include "base/memory/ptr_util.h"
|
|
|
#include "base/notreached.h"
|
|
|
+#include "base/ranges/algorithm.h"
|
|
|
#include "base/stl_util.h"
|
|
|
#include "base/strings/string_util.h"
|
|
|
#include "base/strings/utf_string_conversions.h"
|
|
|
@@ -1581,7 +1581,7 @@ bool ListValue::Remove(size_t index, std
|
|
|
}
|
|
|
|
|
|
bool ListValue::Remove(const Value& value, size_t* index) {
|
|
|
- auto it = std::find(list().begin(), list().end(), value);
|
|
|
+ auto it = ranges::find(list(), value);
|
|
|
|
|
|
if (it == list().end())
|
|
|
return false;
|
|
|
@@ -1659,7 +1659,7 @@ bool ListValue::Insert(size_t index, std
|
|
|
}
|
|
|
|
|
|
ListValue::const_iterator ListValue::Find(const Value& value) const {
|
|
|
- return std::find(GetList().begin(), GetList().end(), value);
|
|
|
+ return ranges::find(GetList(), value);
|
|
|
}
|
|
|
|
|
|
void ListValue::Swap(ListValue* other) {
|
|
|
diff -up chromium-86.0.4240.111/content/public/browser/content_browser_client.cc.a61fb57e chromium-86.0.4240.111/content/public/browser/content_browser_client.cc
|
|
|
--- chromium-86.0.4240.111/content/public/browser/content_browser_client.cc.a61fb57e 2020-10-20 20:14:33.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/content/public/browser/content_browser_client.cc 2020-10-21 17:11:20.019228880 -0400
|
|
|
@@ -9,7 +9,7 @@
|
|
|
// declarations instead of including more headers. If that is infeasible, adjust
|
|
|
// the limit. For more info, see
|
|
|
// https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
|
|
|
-#pragma clang max_tokens_here 880000
|
|
|
+#pragma clang max_tokens_here 910000
|
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
diff -up chromium-86.0.4240.111/third_party/blink/renderer/core/dom/document.cc.a61fb57e chromium-86.0.4240.111/third_party/blink/renderer/core/dom/document.cc
|
|
|
--- chromium-86.0.4240.111/third_party/blink/renderer/core/dom/document.cc.a61fb57e 2020-10-20 20:14:40.000000000 -0400
|
|
|
+++ chromium-86.0.4240.111/third_party/blink/renderer/core/dom/document.cc 2020-10-21 17:11:20.021228898 -0400
|
|
|
@@ -33,7 +33,7 @@
|
|
|
// instead of including more headers. If that is infeasible, adjust the limit.
|
|
|
// For more info, see
|
|
|
// https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
|
|
|
-#pragma clang max_tokens_here 900000
|
|
|
+#pragma clang max_tokens_here 960000
|
|
|
|
|
|
#include <memory>
|
|
|
#include <utility>
|