From 01eca140bc224b12d19e80068ee7e201d4427a5a Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Mon, 19 Oct 2020 18:16:38 -0400 Subject: [PATCH 01/10] add linux/fcntl.h to el7 patch --- chromium-86.0.4240.75-epel7-no-kcmp-h.patch | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chromium-86.0.4240.75-epel7-no-kcmp-h.patch b/chromium-86.0.4240.75-epel7-no-kcmp-h.patch index f12ecf69..40fd76df 100644 --- a/chromium-86.0.4240.75-epel7-no-kcmp-h.patch +++ b/chromium-86.0.4240.75-epel7-no-kcmp-h.patch @@ -1,7 +1,7 @@ diff -up chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc.epel7-kcmp chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc --- chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc.epel7-kcmp 2020-10-19 11:33:27.395594061 -0400 +++ chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc 2020-10-19 11:33:41.703706818 -0400 -@@ -6,7 +6,9 @@ +@@ -6,7 +6,10 @@ #include #include @@ -9,6 +9,7 @@ diff -up chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linu +#ifndef KCMP_FILE +#define KCMP_FILE 0 +#endif ++#include #include // Some arch's (arm64 for instance) unistd.h don't pull in symbols used here From 7aaf58bd2c58495bf63cb15bfe1dcd274ad0aed9 Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Mon, 19 Oct 2020 19:08:27 -0400 Subject: [PATCH 02/10] try this fcntl magic --- chromium-86.0.4240.75-epel7-no-kcmp-h.patch | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/chromium-86.0.4240.75-epel7-no-kcmp-h.patch b/chromium-86.0.4240.75-epel7-no-kcmp-h.patch index 40fd76df..5fe60033 100644 --- a/chromium-86.0.4240.75-epel7-no-kcmp-h.patch +++ b/chromium-86.0.4240.75-epel7-no-kcmp-h.patch @@ -1,15 +1,16 @@ diff -up chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc.epel7-kcmp chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc ---- chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc.epel7-kcmp 2020-10-19 11:33:27.395594061 -0400 -+++ chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc 2020-10-19 11:33:41.703706818 -0400 -@@ -6,7 +6,10 @@ +--- chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc.epel7-kcmp 2020-10-19 19:05:20.249786458 -0400 ++++ chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc 2020-10-19 19:07:09.814720097 -0400 +@@ -5,8 +5,10 @@ + #include "sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.h" #include - #include +-#include -#include ++#include +#ifndef KCMP_FILE +#define KCMP_FILE 0 +#endif -+#include #include // Some arch's (arm64 for instance) unistd.h don't pull in symbols used here From 8ea64328ba73593c8a68b01abd7dc7897ad04b45 Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Tue, 20 Oct 2020 11:15:40 -0400 Subject: [PATCH 03/10] okay, do it the hard way --- chromium-86.0.4240.75-epel7-no-kcmp-h.patch | 23 ++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/chromium-86.0.4240.75-epel7-no-kcmp-h.patch b/chromium-86.0.4240.75-epel7-no-kcmp-h.patch index 5fe60033..fdd65ffc 100644 --- a/chromium-86.0.4240.75-epel7-no-kcmp-h.patch +++ b/chromium-86.0.4240.75-epel7-no-kcmp-h.patch @@ -1,15 +1,28 @@ diff -up chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc.epel7-kcmp chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc --- chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc.epel7-kcmp 2020-10-19 19:05:20.249786458 -0400 -+++ chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc 2020-10-19 19:07:09.814720097 -0400 -@@ -5,8 +5,10 @@ - #include "sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.h" ++++ chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linux.cc 2020-10-20 10:50:21.560402023 -0400 +@@ -6,7 +6,24 @@ #include --#include + #include -#include -+#include +#ifndef KCMP_FILE +#define KCMP_FILE 0 ++#endif ++#ifndef F_LINUX_SPECIFIC_BASE ++#define F_LINUX_SPECIFIC_BASE 1024 ++#endif ++#ifndef F_SEAL_SEAL ++#define F_SEAL_SEAL 0x0001 ++#endif ++#ifndef F_SEAL_SHRINK ++#define F_SEAL_SHRINK 0x0002 ++#endif ++#ifndef F_SEAL_GROW ++#define F_SEAL_GROW 0x0004 ++#endif ++#ifndef F_ADD_SEALS ++#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) +#endif #include From 7147a53f33a8ec1961a82d8c828c7889208c0acf Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Tue, 20 Oct 2020 12:38:24 -0400 Subject: [PATCH 04/10] moar el7 love --- chromium-86.0.4240.75-epel7-no-kcmp-h.patch | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/chromium-86.0.4240.75-epel7-no-kcmp-h.patch b/chromium-86.0.4240.75-epel7-no-kcmp-h.patch index fdd65ffc..93d98715 100644 --- a/chromium-86.0.4240.75-epel7-no-kcmp-h.patch +++ b/chromium-86.0.4240.75-epel7-no-kcmp-h.patch @@ -27,3 +27,29 @@ diff -up chromium-86.0.4240.75/sandbox/policy/linux/bpf_cros_amd_gpu_policy_linu #include // Some arch's (arm64 for instance) unistd.h don't pull in symbols used here +diff -up chromium-86.0.4240.75/sandbox/policy/linux/bpf_gpu_policy_linux.cc.epel7-kcmp chromium-86.0.4240.75/sandbox/policy/linux/bpf_gpu_policy_linux.cc +--- chromium-86.0.4240.75/sandbox/policy/linux/bpf_gpu_policy_linux.cc.epel7-kcmp 2020-10-20 11:58:00.449812627 -0400 ++++ chromium-86.0.4240.75/sandbox/policy/linux/bpf_gpu_policy_linux.cc 2020-10-20 11:58:32.919071919 -0400 +@@ -22,6 +22,22 @@ + #include "sandbox/policy/linux/sandbox_linux.h" + #include "sandbox/policy/linux/sandbox_seccomp_bpf_linux.h" + ++#ifndef F_LINUX_SPECIFIC_BASE ++#define F_LINUX_SPECIFIC_BASE 1024 ++#endif ++#ifndef F_SEAL_SEAL ++#define F_SEAL_SEAL 0x0001 ++#endif ++#ifndef F_SEAL_SHRINK ++#define F_SEAL_SHRINK 0x0002 ++#endif ++#ifndef F_SEAL_GROW ++#define F_SEAL_GROW 0x0004 ++#endif ++#ifndef F_ADD_SEALS ++#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) ++#endif ++ + using sandbox::bpf_dsl::Allow; + using sandbox::bpf_dsl::Arg; + using sandbox::bpf_dsl::Error; From ea12acad9f44ecce2092533ecc3ebc7fa2943e1a Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Tue, 20 Oct 2020 18:32:55 -0400 Subject: [PATCH 05/10] use bundled zlib/minizip on el7 (thanks Red Hat. :P) --- chromium.spec | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/chromium.spec b/chromium.spec index 6466bced..a8fd726e 100644 --- a/chromium.spec +++ b/chromium.spec @@ -118,6 +118,13 @@ BuildRequires: libicu-devel >= 5.4 # This can be revisited once we upgrade to Python 3 %global bundlepylibs 1 +# RHEL 7.9 dropped minizip. +# It exists everywhere else though. +%global bundleminizip 0 +%if 0%{?rhel} == 7 +%global bundleminizip 1 +%endif + # Chromium used to break on wayland, hidpi, and colors with gtk3 enabled. # Hopefully it does not anymore. %global gtk3 1 @@ -178,7 +185,7 @@ Name: chromium%{chromium_channel}%{nsuffix} Name: chromium%{chromium_channel} %endif Version: %{majorversion}.0.4240.75 -Release: 1%{?dist} +Release: 2%{?dist} %if %{?freeworld} %if %{?shared} # chromium-libs-media-freeworld @@ -379,8 +386,8 @@ BuildRequires: minizip-compat-devel %if 0%{?rhel} >= 8 BuildRequires: minizip-compat-devel %else -# RHEL 7 and older uses the old minizip -BuildRequires: minizip-devel +# RHEL 7 used to have minizip, but as of 7.9, it does not. +# BuildRequires: minizip-devel %endif %endif # RHEL 7's nodejs is too old @@ -754,8 +761,12 @@ Summary: Files needed for both the headless_shell and full Chromium %if 0%{?fedora} >= 30 Requires: minizip-compat%{_isa} %else +%if %{?rhel} == 7 +# Do nothing +%else Requires: minizip%{_isa} %endif +%endif # -common doesn't have chrome-remote-desktop bits # but we need to clean it up if it gets disabled again # NOTE: Check obsoletes version to be sure it matches @@ -1327,7 +1338,6 @@ sed -i 's|/opt/google/chrome-remote-desktop|%{crd_path}|g' remoting/host/setup/d export PATH=$PATH:%{_builddir}/depot_tools build/linux/unbundle/replace_gn_files.py --system-libraries \ - flac \ %if 0%{?bundlefontconfig} %else fontconfig \ @@ -1377,7 +1387,11 @@ build/linux/unbundle/replace_gn_files.py --system-libraries \ %else re2 \ %endif - zlib +%if 0%{?bundleminizip} +%else + zlib \ +%endif + flac # fix arm gcc sed -i 's|arm-linux-gnueabihf-|arm-linux-gnu-|g' build/toolchain/linux/BUILD.gn @@ -1905,6 +1919,9 @@ getent group chrome-remote-desktop >/dev/null || groupadd -r chrome-remote-deskt %changelog +* Tue Oct 20 2020 Tom Callaway - 86.0.4240.75-2 +- use bundled zlib/minizip on el7 (thanks Red Hat. :P) + * Wed Oct 14 2020 Tom Callaway - 86.0.4240.75-1 - update to 86.0.4240.75 From 0f68f3eb4aa8bf8805e48f04cae781284bf3e784 Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Wed, 21 Oct 2020 07:24:32 -0400 Subject: [PATCH 06/10] fun with zlib on el7 continues --- chromium.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/chromium.spec b/chromium.spec index a8fd726e..72bcd7d7 100644 --- a/chromium.spec +++ b/chromium.spec @@ -869,7 +869,9 @@ udev. # Short term fixes (usually gcc and backports) %patch50 -p1 -b .gettid-fix %patch51 -p1 -b .gcc-remoting-constexpr +%if 0%{?fedora} || 0%{?rhel} >= 8 %patch52 -p1 -b .unbundle-zlib +%endif %patch53 -p1 -b .gcc-include-memory %patch54 -p1 -b .base-gcc-no-alignas %patch55 -p1 -b .protobuf-export From 3ee5bffeaa1597d65ca5ba698f49f8398a9b30df Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Wed, 21 Oct 2020 17:13:51 -0400 Subject: [PATCH 07/10] 86.0.4240.111 and more fixes --- chromium-86-use-range-based-algorithms.patch | 1500 ++++++++++++++++++ chromium-87-CursorFactory-include.patch | 36 + chromium-87-openscreen-include.patch | 25 + chromium.spec | 11 +- sources | 2 +- 5 files changed, 1571 insertions(+), 3 deletions(-) create mode 100644 chromium-86-use-range-based-algorithms.patch create mode 100644 chromium-87-CursorFactory-include.patch create mode 100644 chromium-87-openscreen-include.patch diff --git a/chromium-86-use-range-based-algorithms.patch b/chromium-86-use-range-based-algorithms.patch new file mode 100644 index 00000000..afbcb6ef --- /dev/null +++ b/chromium-86-use-range-based-algorithms.patch @@ -0,0 +1,1500 @@ +diff -up chromium-86.0.4240.75/base/callback_list.h.a61fb57e chromium-86.0.4240.75/base/callback_list.h +--- chromium-86.0.4240.75/base/callback_list.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/callback_list.h 2020-10-21 16:38:29.003091331 -0400 +@@ -5,7 +5,6 @@ + #ifndef BASE_CALLBACK_LIST_H_ + #define BASE_CALLBACK_LIST_H_ + +-#include + #include + #include + #include +@@ -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.75/base/command_line.cc.a61fb57e chromium-86.0.4240.75/base/command_line.cc +--- chromium-86.0.4240.75/base/command_line.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/command_line.cc 2020-10-21 16:38:29.003091331 -0400 +@@ -4,13 +4,13 @@ + + #include "base/command_line.h" + +-#include + #include + + #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.75/base/containers/checked_range_unittest.cc.a61fb57e chromium-86.0.4240.75/base/containers/checked_range_unittest.cc +--- chromium-86.0.4240.75/base/containers/checked_range_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/containers/checked_range_unittest.cc 2020-10-21 16:38:29.003091331 -0400 +@@ -8,6 +8,7 @@ + #include + #include + ++#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 vector = {3, 1, 4, 2, 5}; + CheckedContiguousRange> 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.75/base/containers/circular_deque.h.a61fb57e chromium-86.0.4240.75/base/containers/circular_deque.h +--- chromium-86.0.4240.75/base/containers/circular_deque.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/containers/circular_deque.h 2020-10-21 16:38:29.003091331 -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 + size_t Erase(circular_deque& 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& containe + + template + size_t EraseIf(circular_deque& 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.75/base/containers/flat_map_unittest.cc.a61fb57e chromium-86.0.4240.75/base/containers/flat_map_unittest.cc +--- chromium-86.0.4240.75/base/containers/flat_map_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/containers/flat_map_unittest.cc 2020-10-21 16:38:29.003091331 -0400 +@@ -8,6 +8,7 @@ + #include + + #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 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 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 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 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.75/base/containers/flat_tree.h.a61fb57e chromium-86.0.4240.75/base/containers/flat_tree.h +--- chromium-86.0.4240.75/base/containers/flat_tree.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/containers/flat_tree.h 2020-10-21 16:38:29.004091339 -0400 +@@ -11,6 +11,7 @@ + #include + #include + ++#include "base/ranges/algorithm.h" + #include "base/stl_util.h" + #include "base/template_util.h" + +@@ -753,11 +754,10 @@ template ::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_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 +@@ -904,7 +904,7 @@ auto flat_tree& 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& + 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.75/base/containers/flat_tree_unittest.cc.a61fb57e chromium-86.0.4240.75/base/containers/flat_tree_unittest.cc +--- chromium-86.0.4240.75/base/containers/flat_tree_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/containers/flat_tree_unittest.cc 2020-10-21 16:38:29.004091339 -0400 +@@ -35,6 +35,7 @@ + #include + #include + ++#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.75/base/containers/span_unittest.cc.a61fb57e chromium-86.0.4240.75/base/containers/span_unittest.cc +--- chromium-86.0.4240.75/base/containers/span_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/containers/span_unittest.cc 2020-10-21 16:38:29.004091339 -0400 +@@ -6,7 +6,6 @@ + + #include + +-#include + #include + #include + #include +@@ -14,6 +13,7 @@ + #include + + #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 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 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.75/base/containers/unique_ptr_adapters_unittest.cc.a61fb57e chromium-86.0.4240.75/base/containers/unique_ptr_adapters_unittest.cc +--- chromium-86.0.4240.75/base/containers/unique_ptr_adapters_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/containers/unique_ptr_adapters_unittest.cc 2020-10-21 16:38:29.004091339 -0400 +@@ -4,10 +4,10 @@ + + #include "base/containers/unique_ptr_adapters.h" + +-#include + #include + #include + ++#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(foo1)); ++ auto iter = ranges::find_if(v, UniquePtrMatcher(foo1)); + ASSERT_TRUE(iter != v.end()); + EXPECT_EQ(foo1, iter->get()); + } + + { +- auto iter = std::find_if(v.begin(), v.end(), UniquePtrMatcher(foo2)); ++ auto iter = ranges::find_if(v, UniquePtrMatcher(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(foo1)); ++ auto iter = ranges::find_if(v, UniquePtrMatcher(foo1)); + ASSERT_TRUE(iter != v.end()); + EXPECT_EQ(foo1, iter->get()); + } + + { +- auto iter = std::find_if(v.begin(), v.end(), +- UniquePtrMatcher(foo2)); ++ auto iter = ranges::find_if(v, UniquePtrMatcher(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()); + } +diff -up chromium-86.0.4240.75/base/debug/activity_analyzer.cc.a61fb57e chromium-86.0.4240.75/base/debug/activity_analyzer.cc +--- chromium-86.0.4240.75/base/debug/activity_analyzer.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/debug/activity_analyzer.cc 2020-10-21 16:38:29.004091339 -0400 +@@ -4,7 +4,6 @@ + + #include "base/debug/activity_analyzer.h" + +-#include + #include + + #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.75/base/debug/task_trace.cc.a61fb57e chromium-86.0.4240.75/base/debug/task_trace.cc +--- chromium-86.0.4240.75/base/debug/task_trace.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/debug/task_trace.cc 2020-10-21 16:38:29.004091339 -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 + #endif // OS_ANDROID + +-#include + #include + #include + +@@ -55,8 +55,7 @@ TaskTrace::TaskTrace() { + return; + std::array 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.75/base/feature_list_unittest.cc.a61fb57e chromium-86.0.4240.75/base/feature_list_unittest.cc +--- chromium-86.0.4240.75/base/feature_list_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/feature_list_unittest.cc 2020-10-21 16:38:29.005091348 -0400 +@@ -6,7 +6,6 @@ + + #include + +-#include + #include + #include + +@@ -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 features = + FeatureList::SplitFeatureListString(feature_list); +- std::sort(features.begin(), features.end()); ++ ranges::sort(features); + return JoinString(features, ","); + } + +diff -up chromium-86.0.4240.75/base/hash/sha1_perftest.cc.a61fb57e chromium-86.0.4240.75/base/hash/sha1_perftest.cc +--- chromium-86.0.4240.75/base/hash/sha1_perftest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/hash/sha1_perftest.cc 2020-10-21 16:38:29.005091348 -0400 +@@ -6,11 +6,11 @@ + + #include + #include +-#include + #include + #include + + #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 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.75/base/i18n/break_iterator_unittest.cc.a61fb57e chromium-86.0.4240.75/base/i18n/break_iterator_unittest.cc +--- chromium-86.0.4240.75/base/i18n/break_iterator_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/i18n/break_iterator_unittest.cc 2020-10-21 16:38:29.005091348 -0400 +@@ -7,6 +7,7 @@ + #include + #include + ++#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.75/base/immediate_crash_unittest.cc.a61fb57e chromium-86.0.4240.75/base/immediate_crash_unittest.cc +diff -up chromium-86.0.4240.75/base/json/json_parser.cc.a61fb57e chromium-86.0.4240.75/base/json/json_parser.cc +--- chromium-86.0.4240.75/base/json/json_parser.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/json/json_parser.cc 2020-10-21 16:38:29.005091348 -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 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.75/base/memory/platform_shared_memory_region_unittest.cc.a61fb57e chromium-86.0.4240.75/base/memory/platform_shared_memory_region_unittest.cc +--- chromium-86.0.4240.75/base/memory/platform_shared_memory_region_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/memory/platform_shared_memory_region_unittest.cc 2020-10-21 16:38:29.005091348 -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 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(addr); +- }); ++ auto it = ranges::find_if( ++ regions, [addr](const base::debug::MappedMemoryRegion& region) { ++ return region.start == reinterpret_cast(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.75/base/memory/shared_memory_mapping_unittest.cc.a61fb57e chromium-86.0.4240.75/base/memory/shared_memory_mapping_unittest.cc +--- chromium-86.0.4240.75/base/memory/shared_memory_mapping_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/memory/shared_memory_mapping_unittest.cc 2020-10-21 16:38:29.005091348 -0400 +@@ -6,12 +6,12 @@ + + #include + +-#include + #include + + #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 read_span = read_mapping_.GetMemoryAsSpan(); + 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 read_span_2 = read_mapping_.GetMemoryAsSpan(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.75/base/metrics/histogram.cc.a61fb57e chromium-86.0.4240.75/base/metrics/histogram.cc +--- chromium-86.0.4240.75/base/metrics/histogram.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/metrics/histogram.cc 2020-10-21 16:38:29.006091357 -0400 +@@ -13,7 +13,6 @@ + #include + #include + +-#include + #include + #include + +@@ -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 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.75/base/metrics/statistics_recorder.cc.a61fb57e chromium-86.0.4240.75/base/metrics/statistics_recorder.cc +--- chromium-86.0.4240.75/base/metrics/statistics_recorder.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/metrics/statistics_recorder.cc 2020-10-21 16:38:29.006091357 -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.75/base/observer_list.h.a61fb57e chromium-86.0.4240.75/base/observer_list.h +--- chromium-86.0.4240.75/base/observer_list.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/observer_list.h 2020-10-21 16:44:23.777189648 -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.75/base/process/process_metrics_unittest.cc.a61fb57e chromium-86.0.4240.75/base/process/process_metrics_unittest.cc +--- chromium-86.0.4240.75/base/process/process_metrics_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/process/process_metrics_unittest.cc 2020-10-21 16:38:29.006091357 -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& 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& 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& 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& 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.75/base/profiler/arm_cfi_table.cc.a61fb57e chromium-86.0.4240.75/base/profiler/arm_cfi_table.cc +--- chromium-86.0.4240.75/base/profiler/arm_cfi_table.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/profiler/arm_cfi_table.cc 2020-10-21 16:38:29.006091357 -0400 +@@ -4,7 +4,7 @@ + + #include "base/profiler/arm_cfi_table.h" + +-#include ++#include "base/ranges/algorithm.h" + + namespace base { + +@@ -91,8 +91,7 @@ Optional 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 ArmCFI + return last_frame_entry; + } + +-} // namespace base +\ No newline at end of file ++} // namespace base +diff -up chromium-86.0.4240.75/base/profiler/metadata_recorder_unittest.cc.a61fb57e chromium-86.0.4240.75/base/profiler/metadata_recorder_unittest.cc +--- chromium-86.0.4240.75/base/profiler/metadata_recorder_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/profiler/metadata_recorder_unittest.cc 2020-10-21 16:38:29.006091357 -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.75/base/profiler/module_cache.cc.a61fb57e chromium-86.0.4240.75/base/profiler/module_cache.cc +--- chromium-86.0.4240.75/base/profiler/module_cache.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/profiler/module_cache.cc 2020-10-21 16:38:29.007091366 -0400 +@@ -4,10 +4,11 @@ + + #include "base/profiler/module_cache.h" + +-#include + #include + #include + ++#include "base/ranges/algorithm.h" ++ + namespace base { + + namespace { +diff -up chromium-86.0.4240.75/base/profiler/stack_sampler_impl.cc.a61fb57e chromium-86.0.4240.75/base/profiler/stack_sampler_impl.cc +--- chromium-86.0.4240.75/base/profiler/stack_sampler_impl.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/profiler/stack_sampler_impl.cc 2020-10-21 16:38:29.007091366 -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 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) { +- return unwinder->CanUnwindFrom(stack.back()); +- }); ++ auto unwinder = ranges::find_if( ++ unwinders, [&stack](const std::unique_ptr& unwinder) { ++ return unwinder->CanUnwindFrom(stack.back()); ++ }); + if (unwinder == unwinders.end()) + return stack; + +diff -up chromium-86.0.4240.75/base/profiler/stack_sampling_profiler_unittest.cc.a61fb57e chromium-86.0.4240.75/base/profiler/stack_sampling_profiler_unittest.cc +--- chromium-86.0.4240.75/base/profiler/stack_sampling_profiler_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/profiler/stack_sampling_profiler_unittest.cc 2020-10-21 16:38:29.007091366 -0400 +@@ -5,7 +5,6 @@ + #include + #include + +-#include + #include + #include + #include +@@ -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>& infos) { + // Map unique_ptrs to something that WaitMany can accept. + std::vector sampling_completed_rawptrs(infos.size()); +- std::transform(infos.begin(), infos.end(), sampling_completed_rawptrs.begin(), +- [](const std::unique_ptr& info) { +- return &info.get()->completed; +- }); ++ ranges::transform(infos, sampling_completed_rawptrs.begin(), ++ [](const std::unique_ptr& 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.75/base/sampling_heap_profiler/poisson_allocation_sampler.cc.a61fb57e chromium-86.0.4240.75/base/sampling_heap_profiler/poisson_allocation_sampler.cc +--- chromium-86.0.4240.75/base/sampling_heap_profiler/poisson_allocation_sampler.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/sampling_heap_profiler/poisson_allocation_sampler.cc 2020-10-21 16:38:29.007091366 -0400 +@@ -4,7 +4,6 @@ + + #include "base/sampling_heap_profiler/poisson_allocation_sampler.h" + +-#include + #include + #include + #include +@@ -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.75/base/scoped_observer.h.a61fb57e chromium-86.0.4240.75/base/scoped_observer.h +--- chromium-86.0.4240.75/base/scoped_observer.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/scoped_observer.h 2020-10-21 16:47:44.604936721 -0400 +@@ -7,11 +7,11 @@ + + #include + +-#include + #include + + #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.75/base/strings/abseil_string_conversions.cc.a61fb57e chromium-86.0.4240.75/base/strings/abseil_string_conversions.cc +--- chromium-86.0.4240.75/base/strings/abseil_string_conversions.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/strings/abseil_string_conversions.cc 2020-10-21 16:38:29.007091366 -0400 +@@ -4,10 +4,10 @@ + + #include "base/strings/abseil_string_conversions.h" + +-#include + #include + + #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 StringPiecesToStringViews( + span pieces) { + std::vector views(pieces.size()); +- std::transform(pieces.begin(), pieces.end(), views.begin(), +- &StringPieceToStringView); ++ ranges::transform(pieces, views.begin(), &StringPieceToStringView); + return views; + } + + std::vector StringViewsToStringPieces( + span views) { + std::vector 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.75/base/strings/string_util_internal.h.a61fb57e chromium-86.0.4240.75/base/strings/string_util_internal.h +--- chromium-86.0.4240.75/base/strings/string_util_internal.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/strings/string_util_internal.h 2020-10-21 16:38:29.007091366 -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(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.75/base/synchronization/waitable_event_posix.cc.a61fb57e chromium-86.0.4240.75/base/synchronization/waitable_event_posix.cc +--- chromium-86.0.4240.75/base/synchronization/waitable_event_posix.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/synchronization/waitable_event_posix.cc 2020-10-21 16:38:29.008091375 -0400 +@@ -4,13 +4,13 @@ + + #include + +-#include + #include + #include + + #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.75/base/task/common/checked_lock_impl.cc.a61fb57e chromium-86.0.4240.75/base/task/common/checked_lock_impl.cc +--- chromium-86.0.4240.75/base/task/common/checked_lock_impl.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/task/common/checked_lock_impl.cc 2020-10-21 16:38:29.008091375 -0400 +@@ -4,12 +4,12 @@ + + #include "base/task/common/checked_lock_impl.h" + +-#include + #include + #include + + #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.75/base/task/common/operations_controller_unittest.cc.a61fb57e chromium-86.0.4240.75/base/task/common/operations_controller_unittest.cc +--- chromium-86.0.4240.75/base/task/common/operations_controller_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/task/common/operations_controller_unittest.cc 2020-10-21 16:38:29.008091375 -0400 +@@ -8,6 +8,7 @@ + #include + #include + ++#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.75/base/task/common/task_annotator.cc.a61fb57e chromium-86.0.4240.75/base/task/common/task_annotator.cc +--- chromium-86.0.4240.75/base/task/common/task_annotator.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/task/common/task_annotator.cc 2020-10-21 16:48:17.376221810 -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(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(pending_task->ipc_hash); + debug::Alias(&task_backtrace); +diff -up chromium-86.0.4240.75/base/task/sequence_manager/sequence_manager_impl.cc.a61fb57e chromium-86.0.4240.75/base/task/sequence_manager/sequence_manager_impl.cc +--- chromium-86.0.4240.75/base/task/sequence_manager/sequence_manager_impl.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/task/sequence_manager/sequence_manager_impl.cc 2020-10-21 16:38:29.008091375 -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 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.75/base/task/sequence_manager/task_queue_impl.cc.a61fb57e chromium-86.0.4240.75/base/task/sequence_manager/task_queue_impl.cc +--- chromium-86.0.4240.75/base/task/sequence_manager/task_queue_impl.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/task/sequence_manager/task_queue_impl.cc 2020-10-21 16:38:29.008091375 -0400 +@@ -10,6 +10,7 @@ + #include + + #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.75/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc.a61fb57e chromium-86.0.4240.75/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc +--- chromium-86.0.4240.75/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc 2020-10-21 16:38:29.009091383 -0400 +@@ -4,7 +4,6 @@ + + #include "base/task/thread_pool/pooled_single_thread_task_runner_manager.h" + +-#include + #include + #include + #include +@@ -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.75/base/task/thread_pool/thread_group_impl.cc.a61fb57e chromium-86.0.4240.75/base/task/thread_pool/thread_group_impl.cc +--- chromium-86.0.4240.75/base/task/thread_pool/thread_group_impl.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/task/thread_pool/thread_group_impl.cc 2020-10-21 16:38:29.009091383 -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>& workers, + const WorkerThread* worker) { +- auto it = std::find_if(workers.begin(), workers.end(), +- [worker](const scoped_refptr& i) { +- return i.get() == worker; +- }); ++ auto it = ++ ranges::find_if(workers, [worker](const scoped_refptr& 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.75/base/task/thread_pool/worker_thread_stack.cc.a61fb57e chromium-86.0.4240.75/base/task/thread_pool/worker_thread_stack.cc +--- chromium-86.0.4240.75/base/task/thread_pool/worker_thread_stack.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/task/thread_pool/worker_thread_stack.cc 2020-10-21 16:38:29.009091383 -0400 +@@ -4,9 +4,8 @@ + + #include "base/task/thread_pool/worker_thread_stack.h" + +-#include +- + #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.75/base/test/launcher/test_launcher.cc.a61fb57e chromium-86.0.4240.75/base/test/launcher/test_launcher.cc +--- chromium-86.0.4240.75/base/test/launcher/test_launcher.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/test/launcher/test_launcher.cc 2020-10-21 16:38:29.009091383 -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 + #include + #include + + #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& 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.75/base/test/trace_event_analyzer.cc.a61fb57e chromium-86.0.4240.75/base/test/trace_event_analyzer.cc +--- chromium-86.0.4240.75/base/test/trace_event_analyzer.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/test/trace_event_analyzer.cc 2020-10-21 16:38:29.010091392 -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(num_deltas); + + double sum_mean_offsets_squared = 0.0; +diff -up chromium-86.0.4240.75/base/threading/hang_watcher.cc.a61fb57e chromium-86.0.4240.75/base/threading/hang_watcher.cc +--- chromium-86.0.4240.75/base/threading/hang_watcher.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/threading/hang_watcher.cc 2020-10-21 16:38:29.010091392 -0400 +@@ -4,7 +4,6 @@ + + #include "base/threading/hang_watcher.h" + +-#include + #include + #include + +@@ -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& 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& state) { +- return state.get() == current_hang_watch_state; +- }); ++ auto it = ranges::find_if( ++ watch_states_, ++ [current_hang_watch_state]( ++ const std::unique_ptr& 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.75/base/trace_event/trace_log.cc.a61fb57e chromium-86.0.4240.75/base/trace_event/trace_log.cc +--- chromium-86.0.4240.75/base/trace_event/trace_log.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/trace_event/trace_log.cc 2020-10-21 16:38:29.010091392 -0400 +@@ -4,7 +4,6 @@ + + #include "base/trace_event/trace_log.h" + +-#include + #include + #include + #include +@@ -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.75/base/values.cc.a61fb57e chromium-86.0.4240.75/base/values.cc +--- chromium-86.0.4240.75/base/values.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 ++++ chromium-86.0.4240.75/base/values.cc 2020-10-21 16:38:29.010091392 -0400 +@@ -6,7 +6,6 @@ + + #include + +-#include + #include + #include + #include +@@ -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.75/content/public/browser/content_browser_client.cc.a61fb57e chromium-86.0.4240.75/content/public/browser/content_browser_client.cc +--- chromium-86.0.4240.75/content/public/browser/content_browser_client.cc.a61fb57e 2020-10-21 16:38:29.011091401 -0400 ++++ chromium-86.0.4240.75/content/public/browser/content_browser_client.cc 2020-10-21 16:48:43.858452175 -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 + +diff -up chromium-86.0.4240.75/third_party/blink/renderer/core/dom/document.cc.a61fb57e chromium-86.0.4240.75/third_party/blink/renderer/core/dom/document.cc +--- chromium-86.0.4240.75/third_party/blink/renderer/core/dom/document.cc.a61fb57e 2020-10-21 16:38:29.013091419 -0400 ++++ chromium-86.0.4240.75/third_party/blink/renderer/core/dom/document.cc 2020-10-21 16:49:03.209620502 -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 + #include diff --git a/chromium-87-CursorFactory-include.patch b/chromium-87-CursorFactory-include.patch new file mode 100644 index 00000000..98cb9cf7 --- /dev/null +++ b/chromium-87-CursorFactory-include.patch @@ -0,0 +1,36 @@ +From c4f6e8cd34a245c3640b86a91c9694d69594d80b Mon Sep 17 00:00:00 2001 +From: Stephan Hartmann +Date: Wed, 16 Sep 2020 15:05:02 +0000 +Subject: [PATCH] IWYU: ui::CursorFactory is now required independent from + Ozone + +--- + .../ui/views/chrome_browser_main_extra_parts_views_linux.cc | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc +index 5a97d61..ccedd2a 100644 +--- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc ++++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.cc +@@ -7,6 +7,7 @@ + #include "chrome/browser/themes/theme_service_aura_linux.h" + #include "chrome/browser/ui/browser_list.h" + #include "chrome/browser/ui/views/theme_profile_key.h" ++#include "ui/base/cursor/cursor_factory.h" + #include "ui/display/screen.h" + #include "ui/views/linux_ui/linux_ui.h" + +@@ -15,10 +16,6 @@ + #include "ui/gtk/gtk_ui_delegate.h" + #endif + +-#if defined(USE_OZONE) +-#include "ui/base/cursor/cursor_factory.h" +-#endif +- + #if defined(USE_X11) + #include "ui/gfx/x/connection.h" // nogncheck + #if BUILDFLAG(USE_GTK) +-- +2.26.2 + diff --git a/chromium-87-openscreen-include.patch b/chromium-87-openscreen-include.patch new file mode 100644 index 00000000..42545a8c --- /dev/null +++ b/chromium-87-openscreen-include.patch @@ -0,0 +1,25 @@ +From 0c0af4cabb7490db473cd2c28f069956974a4d98 Mon Sep 17 00:00:00 2001 +From: Stephan Hartmann +Date: Fri, 2 Oct 2020 12:11:58 +0000 +Subject: [PATCH] IWYU: uint8_t is defined in stdint.h + +--- + third_party/openscreen/src/util/crypto/random_bytes.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/third_party/openscreen/src/util/crypto/random_bytes.h b/third_party/openscreen/src/util/crypto/random_bytes.h +index 3cb2fa8..025b52c 100644 +--- a/third_party/openscreen/src/util/crypto/random_bytes.h ++++ b/third_party/openscreen/src/util/crypto/random_bytes.h +@@ -7,6 +7,8 @@ + + #include + ++#include ++ + namespace openscreen { + + std::array GenerateRandomBytes16(); +-- +2.26.2 + diff --git a/chromium.spec b/chromium.spec index 72bcd7d7..08b7d050 100644 --- a/chromium.spec +++ b/chromium.spec @@ -184,8 +184,8 @@ Name: chromium%{chromium_channel}%{nsuffix} %else Name: chromium%{chromium_channel} %endif -Version: %{majorversion}.0.4240.75 -Release: 2%{?dist} +Version: %{majorversion}.0.4240.111 +Release: 1%{?dist} %if %{?freeworld} %if %{?shared} # chromium-libs-media-freeworld @@ -275,6 +275,9 @@ Patch70: chromium-84.0.4147.125-i686-fix_textrels.patch Patch71: chromium-84.0.4147.125-aarch64-clearkeycdm-binutils-workaround.patch # https://github.com/chromium/chromium/commit/53478caee862624fc6d73516f8d64253854b146f Patch72: chromium-85.0.4183.102-invalid-end-CookieMonster-53478ca.patch +# EL7 failed to compile without this, but it seems accurate for all branches +# https://github.com/chromium/chromium/commit/a61fb57edb75fcfe251af0e6f66820d13924ad62 +Patch73: chromium-86-use-range-based-algorithms.patch # Use lstdc++ on EPEL7 only Patch101: chromium-75.0.3770.100-epel7-stdc++.patch @@ -892,6 +895,7 @@ udev. %patch70 -p1 -b .i686-textrels %patch71 -p1 -b .aarch64-clearkeycdm-binutils-workaround %patch72 -p1 -b .invalid-end-CookieMonster +%patch73 -p1 -b .a61fb57e # Fedora branded user agent %if 0%{?fedora} @@ -1921,6 +1925,9 @@ getent group chrome-remote-desktop >/dev/null || groupadd -r chrome-remote-deskt %changelog +* Wed Oct 21 2020 Tom Callaway - 86.0.4240.111-1 +- update to 86.0.4240.111 + * Tue Oct 20 2020 Tom Callaway - 86.0.4240.75-2 - use bundled zlib/minizip on el7 (thanks Red Hat. :P) diff --git a/sources b/sources index 3acfc8f1..53c92993 100644 --- a/sources +++ b/sources @@ -20,4 +20,4 @@ SHA512 (xcb-proto-1.14.tar.xz) = de66d568163b6da2be9d6c59984f3afa3acd119a7813786 SHA512 (depot_tools.git-master.tar.gz) = dc323888812b66cc92c53a24a8a58ccf9e2961be67aa21852bd091b8b49569071f06ae9104cb58950e6253ac3a29f0db0663e9f35ef2b1ea28696efb38b42708 SHA512 (NotoSansSymbols2-Regular.ttf) = 2644b42c3fdccfe12395f9b61553aced169a0f1dc09f5a0fd7898e9d0a372ee4422b6b1cdab3c86ecc91db437e9ae8a951e64e85edc3ac9e9fca428852dbb2ad SHA512 (NotoSansTibetan-Regular.ttf) = fb5a48fcaea80eebe7d692f6fcf00d59d47658a358d0ec8e046fc559873f88bd595b2da474d2826abd9e9305f3741c69058d867b1e6048f37fe7d71b5d3af36a -SHA512 (chromium-86.0.4240.75-clean.tar.xz) = 9832895a138758522c1ea926bdf05116b3494196b19852ef0ee85c6fb333afea0d19d9950b74aa93cc6731bafc119768ae610d7c69fd21da10de2b4599006963 +SHA512 (chromium-86.0.4240.111-clean.tar.xz) = 51f779e6f6549442e4392087c3aff48931e254b69ab2bbe9d25c3523de7a62dc9fadd99ba7dd22c614b2031ca93f35184bf14de7fdfb79abc0d5139078d695de From f8ecb3a55335ccec7eaeff8fda4976e3f5a2a43b Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Wed, 21 Oct 2020 17:46:31 -0400 Subject: [PATCH 08/10] more ranges fixes --- chromium-86-use-range-based-algorithms.patch | 5432 +++++++++++++++++- 1 file changed, 5290 insertions(+), 142 deletions(-) diff --git a/chromium-86-use-range-based-algorithms.patch b/chromium-86-use-range-based-algorithms.patch index afbcb6ef..e9ea3f30 100644 --- a/chromium-86-use-range-based-algorithms.patch +++ b/chromium-86-use-range-based-algorithms.patch @@ -1,6 +1,6 @@ -diff -up chromium-86.0.4240.75/base/callback_list.h.a61fb57e chromium-86.0.4240.75/base/callback_list.h ---- chromium-86.0.4240.75/base/callback_list.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/callback_list.h 2020-10-21 16:38:29.003091331 -0400 +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_ @@ -28,9 +28,9 @@ diff -up chromium-86.0.4240.75/base/callback_list.h.a61fb57e chromium-86.0.4240. } // Calls all registered callbacks that are not canceled beforehand. If any -diff -up chromium-86.0.4240.75/base/command_line.cc.a61fb57e chromium-86.0.4240.75/base/command_line.cc ---- chromium-86.0.4240.75/base/command_line.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/command_line.cc 2020-10-21 16:38:29.003091331 -0400 +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" @@ -56,9 +56,9 @@ diff -up chromium-86.0.4240.75/base/command_line.cc.a61fb57e chromium-86.0.4240. if (switch_terminator != args.end()) args.erase(switch_terminator); return args; -diff -up chromium-86.0.4240.75/base/containers/checked_range_unittest.cc.a61fb57e chromium-86.0.4240.75/base/containers/checked_range_unittest.cc ---- chromium-86.0.4240.75/base/containers/checked_range_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/containers/checked_range_unittest.cc 2020-10-21 16:38:29.003091331 -0400 +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 #include @@ -79,9 +79,9 @@ diff -up chromium-86.0.4240.75/base/containers/checked_range_unittest.cc.a61fb57 } TEST(CheckedContiguousRange, DataSizeEmpty_Constexpr) { -diff -up chromium-86.0.4240.75/base/containers/circular_deque.h.a61fb57e chromium-86.0.4240.75/base/containers/circular_deque.h ---- chromium-86.0.4240.75/base/containers/circular_deque.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/containers/circular_deque.h 2020-10-21 16:38:29.003091331 -0400 +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" @@ -108,9 +108,9 @@ diff -up chromium-86.0.4240.75/base/containers/circular_deque.h.a61fb57e chromiu size_t removed = std::distance(it, container.end()); container.erase(it, container.end()); return removed; -diff -up chromium-86.0.4240.75/base/containers/flat_map_unittest.cc.a61fb57e chromium-86.0.4240.75/base/containers/flat_map_unittest.cc ---- chromium-86.0.4240.75/base/containers/flat_map_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/containers/flat_map_unittest.cc 2020-10-21 16:38:29.003091331 -0400 +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 @@ -155,9 +155,9 @@ diff -up chromium-86.0.4240.75/base/containers/flat_map_unittest.cc.a61fb57e chr } } -diff -up chromium-86.0.4240.75/base/containers/flat_tree.h.a61fb57e chromium-86.0.4240.75/base/containers/flat_tree.h ---- chromium-86.0.4240.75/base/containers/flat_tree.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/containers/flat_tree.h 2020-10-21 16:38:29.004091339 -0400 +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 #include @@ -209,9 +209,9 @@ diff -up chromium-86.0.4240.75/base/containers/flat_tree.h.a61fb57e chromium-86. size_t removed = std::distance(it, container.end()); container.erase(it, container.end()); return removed; -diff -up chromium-86.0.4240.75/base/containers/flat_tree_unittest.cc.a61fb57e chromium-86.0.4240.75/base/containers/flat_tree_unittest.cc ---- chromium-86.0.4240.75/base/containers/flat_tree_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/containers/flat_tree_unittest.cc 2020-10-21 16:38:29.004091339 -0400 +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 #include @@ -259,9 +259,9 @@ diff -up chromium-86.0.4240.75/base/containers/flat_tree_unittest.cc.a61fb57e ch } // ---------------------------------------------------------------------------- -diff -up chromium-86.0.4240.75/base/containers/span_unittest.cc.a61fb57e chromium-86.0.4240.75/base/containers/span_unittest.cc ---- chromium-86.0.4240.75/base/containers/span_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/containers/span_unittest.cc 2020-10-21 16:38:29.004091339 -0400 +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 @@ -296,9 +296,9 @@ diff -up chromium-86.0.4240.75/base/containers/span_unittest.cc.a61fb57e chromiu EXPECT_THAT(array, ElementsAre(5, 4, 3, 2, 1)); } -diff -up chromium-86.0.4240.75/base/containers/unique_ptr_adapters_unittest.cc.a61fb57e chromium-86.0.4240.75/base/containers/unique_ptr_adapters_unittest.cc ---- chromium-86.0.4240.75/base/containers/unique_ptr_adapters_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/containers/unique_ptr_adapters_unittest.cc 2020-10-21 16:38:29.004091339 -0400 +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" @@ -360,9 +360,9 @@ diff -up chromium-86.0.4240.75/base/containers/unique_ptr_adapters_unittest.cc.a ASSERT_TRUE(iter != v.end()); EXPECT_EQ(foo2, iter->get()); } -diff -up chromium-86.0.4240.75/base/debug/activity_analyzer.cc.a61fb57e chromium-86.0.4240.75/base/debug/activity_analyzer.cc ---- chromium-86.0.4240.75/base/debug/activity_analyzer.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/debug/activity_analyzer.cc 2020-10-21 16:38:29.004091339 -0400 +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" @@ -388,9 +388,9 @@ diff -up chromium-86.0.4240.75/base/debug/activity_analyzer.cc.a61fb57e chromium } } // namespace debug -diff -up chromium-86.0.4240.75/base/debug/task_trace.cc.a61fb57e chromium-86.0.4240.75/base/debug/task_trace.cc ---- chromium-86.0.4240.75/base/debug/task_trace.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/debug/task_trace.cc 2020-10-21 16:38:29.004091339 -0400 +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" @@ -416,9 +416,9 @@ diff -up chromium-86.0.4240.75/base/debug/task_trace.cc.a61fb57e chromium-86.0.4 size_t length = 0; while (length < task_trace.size() && task_trace[length]) ++length; -diff -up chromium-86.0.4240.75/base/feature_list_unittest.cc.a61fb57e chromium-86.0.4240.75/base/feature_list_unittest.cc ---- chromium-86.0.4240.75/base/feature_list_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/feature_list_unittest.cc 2020-10-21 16:38:29.005091348 -0400 +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 @@ -444,9 +444,9 @@ diff -up chromium-86.0.4240.75/base/feature_list_unittest.cc.a61fb57e chromium-8 return JoinString(features, ","); } -diff -up chromium-86.0.4240.75/base/hash/sha1_perftest.cc.a61fb57e chromium-86.0.4240.75/base/hash/sha1_perftest.cc ---- chromium-86.0.4240.75/base/hash/sha1_perftest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/hash/sha1_perftest.cc 2020-10-21 16:38:29.005091348 -0400 +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 @@ -480,9 +480,9 @@ diff -up chromium-86.0.4240.75/base/hash/sha1_perftest.cc.a61fb57e chromium-86.0 reporter.AddResultList(kMetricThroughput, JoinString(rate_strings, ",")); } -diff -up chromium-86.0.4240.75/base/i18n/break_iterator_unittest.cc.a61fb57e chromium-86.0.4240.75/base/i18n/break_iterator_unittest.cc ---- chromium-86.0.4240.75/base/i18n/break_iterator_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/i18n/break_iterator_unittest.cc 2020-10-21 16:38:29.005091348 -0400 +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 #include @@ -501,10 +501,9 @@ diff -up chromium-86.0.4240.75/base/i18n/break_iterator_unittest.cc.a61fb57e chr EXPECT_TRUE(iter.IsSentenceBoundary(i)) << " at index=" << i; } else { EXPECT_FALSE(iter.IsSentenceBoundary(i)) << " at index=" << i; -diff -up chromium-86.0.4240.75/base/immediate_crash_unittest.cc.a61fb57e chromium-86.0.4240.75/base/immediate_crash_unittest.cc -diff -up chromium-86.0.4240.75/base/json/json_parser.cc.a61fb57e chromium-86.0.4240.75/base/json/json_parser.cc ---- chromium-86.0.4240.75/base/json/json_parser.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/json/json_parser.cc 2020-10-21 16:38:29.005091348 -0400 +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" @@ -522,9 +521,9 @@ diff -up chromium-86.0.4240.75/base/json/json_parser.cc.a61fb57e chromium-86.0.4 return Value(Value::DictStorage(std::move(dict_storage))); } -diff -up chromium-86.0.4240.75/base/memory/platform_shared_memory_region_unittest.cc.a61fb57e chromium-86.0.4240.75/base/memory/platform_shared_memory_region_unittest.cc ---- chromium-86.0.4240.75/base/memory/platform_shared_memory_region_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/memory/platform_shared_memory_region_unittest.cc 2020-10-21 16:38:29.005091348 -0400 +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" @@ -549,9 +548,9 @@ diff -up chromium-86.0.4240.75/base/memory/platform_shared_memory_region_unittes 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.75/base/memory/shared_memory_mapping_unittest.cc.a61fb57e chromium-86.0.4240.75/base/memory/shared_memory_mapping_unittest.cc ---- chromium-86.0.4240.75/base/memory/shared_memory_mapping_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/memory/shared_memory_mapping_unittest.cc 2020-10-21 16:38:29.005091348 -0400 +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 @@ -593,9 +592,9 @@ diff -up chromium-86.0.4240.75/base/memory/shared_memory_mapping_unittest.cc.a61 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.75/base/metrics/histogram.cc.a61fb57e chromium-86.0.4240.75/base/metrics/histogram.cc ---- chromium-86.0.4240.75/base/metrics/histogram.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/metrics/histogram.cc 2020-10-21 16:38:29.006091357 -0400 +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 #include @@ -623,9 +622,9 @@ diff -up chromium-86.0.4240.75/base/metrics/histogram.cc.a61fb57e chromium-86.0. BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); for (uint32_t i = 0; i < ranges.size(); i++) { -diff -up chromium-86.0.4240.75/base/metrics/statistics_recorder.cc.a61fb57e chromium-86.0.4240.75/base/metrics/statistics_recorder.cc ---- chromium-86.0.4240.75/base/metrics/statistics_recorder.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/metrics/statistics_recorder.cc 2020-10-21 16:38:29.006091357 -0400 +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" @@ -678,9 +677,9 @@ diff -up chromium-86.0.4240.75/base/metrics/statistics_recorder.cc.a61fb57e chro histograms.end()); return histograms; } -diff -up chromium-86.0.4240.75/base/observer_list.h.a61fb57e chromium-86.0.4240.75/base/observer_list.h ---- chromium-86.0.4240.75/base/observer_list.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/observer_list.h 2020-10-21 16:44:23.777189648 -0400 +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" @@ -714,9 +713,9 @@ diff -up chromium-86.0.4240.75/base/observer_list.h.a61fb57e chromium-86.0.4240. } // Removes all the observers from this list. -diff -up chromium-86.0.4240.75/base/process/process_metrics_unittest.cc.a61fb57e chromium-86.0.4240.75/base/process/process_metrics_unittest.cc ---- chromium-86.0.4240.75/base/process/process_metrics_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/process/process_metrics_unittest.cc 2020-10-21 16:38:29.006091357 -0400 +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" @@ -775,9 +774,9 @@ diff -up chromium-86.0.4240.75/base/process/process_metrics_unittest.cc.a61fb57e [&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.75/base/profiler/arm_cfi_table.cc.a61fb57e chromium-86.0.4240.75/base/profiler/arm_cfi_table.cc ---- chromium-86.0.4240.75/base/profiler/arm_cfi_table.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/profiler/arm_cfi_table.cc 2020-10-21 16:38:29.006091357 -0400 +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" @@ -804,9 +803,9 @@ diff -up chromium-86.0.4240.75/base/profiler/arm_cfi_table.cc.a61fb57e chromium- -} // namespace base \ No newline at end of file +} // namespace base -diff -up chromium-86.0.4240.75/base/profiler/metadata_recorder_unittest.cc.a61fb57e chromium-86.0.4240.75/base/profiler/metadata_recorder_unittest.cc ---- chromium-86.0.4240.75/base/profiler/metadata_recorder_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/profiler/metadata_recorder_unittest.cc 2020-10-21 16:38:29.006091357 -0400 +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" @@ -824,9 +823,9 @@ diff -up chromium-86.0.4240.75/base/profiler/metadata_recorder_unittest.cc.a61fb MetadataRecorder::ItemArray recorder_items; size_t recorder_item_count = -diff -up chromium-86.0.4240.75/base/profiler/module_cache.cc.a61fb57e chromium-86.0.4240.75/base/profiler/module_cache.cc ---- chromium-86.0.4240.75/base/profiler/module_cache.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/profiler/module_cache.cc 2020-10-21 16:38:29.007091366 -0400 +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" @@ -840,9 +839,9 @@ diff -up chromium-86.0.4240.75/base/profiler/module_cache.cc.a61fb57e chromium-8 namespace base { namespace { -diff -up chromium-86.0.4240.75/base/profiler/stack_sampler_impl.cc.a61fb57e chromium-86.0.4240.75/base/profiler/stack_sampler_impl.cc ---- chromium-86.0.4240.75/base/profiler/stack_sampler_impl.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/profiler/stack_sampler_impl.cc 2020-10-21 16:38:29.007091366 -0400 +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" @@ -867,9 +866,9 @@ diff -up chromium-86.0.4240.75/base/profiler/stack_sampler_impl.cc.a61fb57e chro if (unwinder == unwinders.end()) return stack; -diff -up chromium-86.0.4240.75/base/profiler/stack_sampling_profiler_unittest.cc.a61fb57e chromium-86.0.4240.75/base/profiler/stack_sampling_profiler_unittest.cc ---- chromium-86.0.4240.75/base/profiler/stack_sampling_profiler_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/profiler/stack_sampling_profiler_unittest.cc 2020-10-21 16:38:29.007091366 -0400 +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 #include @@ -901,9 +900,5158 @@ diff -up chromium-86.0.4240.75/base/profiler/stack_sampling_profiler_unittest.cc // Wait for one profiler to finish. return WaitableEvent::WaitMany(sampling_completed_rawptrs.data(), sampling_completed_rawptrs.size()); -diff -up chromium-86.0.4240.75/base/sampling_heap_profiler/poisson_allocation_sampler.cc.a61fb57e chromium-86.0.4240.75/base/sampling_heap_profiler/poisson_allocation_sampler.cc ---- chromium-86.0.4240.75/base/sampling_heap_profiler/poisson_allocation_sampler.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/sampling_heap_profiler/poisson_allocation_sampler.cc 2020-10-21 16:38:29.007091366 -0400 +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 ++#include ++#include ++#include ++#include ++ ++#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 ++constexpr auto ProjectedUnaryPredicate(Pred& pred, Proj& proj) noexcept { ++ return [&pred, &proj](auto&& arg) -> bool { ++ return base::invoke(pred, ++ base::invoke(proj, std::forward(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, Proj1>, ++// projected, Proj2>> ++// ++// Ensures that the return type of `invoke(pred, ...)` is convertible to bool. ++template ++class BinaryPredicateProjector { ++ public: ++ constexpr BinaryPredicateProjector(Pred& pred, Proj1& proj1, Proj2& proj2) ++ : pred_(pred), proj1_(proj1), proj2_(proj2) {} ++ ++ private: ++ template ++ using InvokeResult = invoke_result_t, ++ invoke_result_t>; ++ ++ template > ++ constexpr std::pair GetProjs(priority_tag<3>) const { ++ return {proj1_, proj2_}; ++ } ++ ++ template , ++ typename = InvokeResult> ++ constexpr std::pair GetProjs(priority_tag<2>) const { ++ return {proj2_, proj1_}; ++ } ++ ++ template , ++ typename = InvokeResult> ++ constexpr std::pair GetProjs(priority_tag<1>) const { ++ return {proj1_, proj1_}; ++ } ++ ++ template , ++ typename = InvokeResult> ++ constexpr std::pair GetProjs(priority_tag<0>) const { ++ return {proj2_, proj2_}; ++ } ++ ++ public: ++ template ++ constexpr bool operator()(T&& lhs, U&& rhs) const { ++ auto projs = GetProjs(priority_tag<3>()); ++ return base::invoke(pred_, base::invoke(projs.first, std::forward(lhs)), ++ base::invoke(projs.second, std::forward(rhs))); ++ } ++ ++ private: ++ Pred& pred_; ++ Proj1& proj1_; ++ Proj2& proj2_; ++}; ++ ++// Small wrappers around BinaryPredicateProjector to make the calling side more ++// readable. ++template ++constexpr auto ProjectedBinaryPredicate(Pred& pred, ++ Proj1& proj1, ++ Proj2& proj2) noexcept { ++ return BinaryPredicateProjector(pred, proj1, proj2); ++} ++ ++template ++constexpr auto PermutedProjectedBinaryPredicate(Pred& pred, ++ Proj1& proj1, ++ Proj2& proj2) noexcept { ++ return BinaryPredicateProjector(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 = decltype(std::declval()++)> ++using iterator_category_t = ++ typename std::iterator_traits::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 ++using range_category_t = iterator_category_t>; ++ ++} // 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 ++struct in_fun_result { ++ /* [[no_unique_address]] */ I in; ++ /* [[no_unique_address]] */ F fun; ++ ++ template {} && ++ std::is_convertible{}>> ++ constexpr operator in_fun_result() const& { ++ return {in, fun}; ++ } ++ ++ template {} && ++ std::is_convertible{}>> ++ constexpr operator in_fun_result() && { ++ 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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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 ++using for_each_result = in_fun_result; ++ ++// 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 > ++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{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 > ++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 ++using for_each_n_result = in_fun_result; ++ ++// 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 > ++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{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 > ++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(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 > ++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 > ++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 > ++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 > ++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 > ++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 = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, 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 = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, 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 > ++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 > ++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 > ++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(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 > ++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 > ++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 > ++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 = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, 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 = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, 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 = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, 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 = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, 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 > ++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 > ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::range_category_t> ++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 = internal::iterator_category_t, ++ typename = indirect_result_t>> ++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(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 = internal::iterator_category_t, ++ typename = indirect_result_t, 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 = internal::iterator_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>> ++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(lhs)), ++ base::invoke(proj2, std::forward(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 = internal::range_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, 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 > ++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(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 > ++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 > ++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 > ++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 = internal::iterator_category_t> ++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(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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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(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 > ++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 > ++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 > ++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 = internal::iterator_category_t> ++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(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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 > ++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 > ++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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++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 > ++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 > ++constexpr auto rotate(Range&& range, iterator_t 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 = internal::iterator_category_t> ++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 = internal::iterator_category_t> ++constexpr auto rotate_copy(Range&& range, ++ iterator_t 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` ++// 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 > ++constexpr auto shuffle(RandomAccessIterator first, ++ RandomAccessIterator last, ++ UniformRandomBitGenerator&& g) { ++ std::shuffle(first, last, std::forward(g)); ++ return last; ++} ++ ++// Preconditions: The type `std::remove_reference_t` ++// 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 > ++constexpr auto shuffle(Range&& range, UniformRandomBitGenerator&& g) { ++ return ranges::shuffle(ranges::begin(range), ranges::end(range), ++ std::forward(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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, Proj>>> ++constexpr auto partial_sort(Range&& range, ++ iterator_t 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 = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, Proj2>>, ++ typename = indirect_result_t, Proj2>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, Proj>>> ++constexpr auto nth_element(Range&& range, ++ iterator_t 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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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 > ++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 = internal::iterator_category_t, ++ typename = internal::iterator_category_t> ++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 = internal::iterator_category_t, ++ typename = internal::iterator_category_t> ++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 > ++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 > ++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 = internal::iterator_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, Proj2>>, ++ typename = indirect_result_t, Proj2>, ++ projected, 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 > ++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 > ++constexpr auto inplace_merge(Range&& range, ++ iterator_t 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 = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, Proj2>>, ++ typename = indirect_result_t, Proj2>, ++ projected, 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 = internal::iterator_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, Proj2>>, ++ typename = indirect_result_t, Proj2>, ++ projected, 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 = internal::iterator_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, Proj2>>, ++ typename = indirect_result_t, Proj2>, ++ projected, 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 = internal::iterator_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, Proj2>>, ++ typename = indirect_result_t, Proj2>, ++ projected, 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 = internal::iterator_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = internal::iterator_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, Proj2>>, ++ typename = indirect_result_t, Proj2>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 ++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 ++constexpr T min(std::initializer_list 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 > ++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 ++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 ++constexpr T max(std::initializer_list 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 > ++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 ++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 ++constexpr auto minmax(std::initializer_list ilist, ++ Comp comp = {}, ++ Proj proj = {}) { ++ auto it = ++ std::minmax_element(ranges::begin(ilist), ranges::end(ilist), ++ internal::ProjectedBinaryPredicate(comp, proj, proj)); ++ return std::pair{*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 > ++constexpr auto minmax(Range&& range, Comp comp = {}, Proj proj = {}) { ++ using T = range_value_t; ++ auto it = ++ std::minmax_element(ranges::begin(range), ranges::end(range), ++ internal::ProjectedBinaryPredicate(comp, proj, proj)); ++ return std::pair{*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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 ++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 = internal::iterator_category_t, ++ typename = indirect_result_t, ++ projected>, ++ typename = indirect_result_t, ++ projected>> ++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 = internal::range_category_t, ++ typename = indirect_result_t, Proj1>, ++ projected, Proj2>>, ++ typename = indirect_result_t, Proj2>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 = indirect_result_t, ++ projected>> ++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 = indirect_result_t, Proj>, ++ projected, 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 ++#include ++#include ++ ++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 ++#include ++#include ++#include ++ ++#include "base/template_util.h" ++ ++namespace base { ++ ++namespace internal { ++ ++// Overload for C array. ++template ++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 ++constexpr T* begin(std::array& array, priority_tag<2> tag) { ++ return const_cast(begin(const_cast&>(array), tag)); ++} ++ ++// Overload for const std::array. Required since std::array::begin is not ++// constexpr prior to C++17. ++template ++constexpr const T* begin(const std::array& array, priority_tag<2>) { ++ return N != 0 ? &array[0] : nullptr; ++} ++ ++// Generic container overload. ++template ++constexpr auto begin(Range&& range, priority_tag<1>) ++ -> decltype(std::forward(range).begin()) { ++ return std::forward(range).begin(); ++} ++ ++// Overload for free begin() function. ++template ++constexpr auto begin(Range&& range, priority_tag<0>) ++ -> decltype(begin(std::forward(range))) { ++ return begin(std::forward(range)); ++} ++ ++// Overload for C array. ++template ++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 ++constexpr T* end(std::array& array, priority_tag<2> tag) { ++ return const_cast(end(const_cast&>(array), tag)); ++} ++ ++// Overload for const std::array. Required since std::array::end is not ++// constexpr prior to C++17. ++template ++constexpr const T* end(const std::array& array, priority_tag<2>) { ++ return N != 0 ? (&array[0]) + N : nullptr; ++} ++ ++// Generic container overload. ++template ++constexpr auto end(Range&& range, priority_tag<1>) ++ -> decltype(std::forward(range).end()) { ++ return std::forward(range).end(); ++} ++ ++// Overload for free end() function. ++template ++constexpr auto end(Range&& range, priority_tag<0>) ++ -> decltype(end(std::forward(range))) { ++ return end(std::forward(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 ++constexpr auto begin(Range&& range) noexcept ++ -> decltype(internal::begin(std::forward(range), ++ internal::priority_tag<2>())) { ++ return internal::begin(std::forward(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 ++constexpr auto end(Range&& range) noexcept ++ -> decltype(internal::end(std::forward(range), ++ internal::priority_tag<2>())) { ++ return internal::end(std::forward(range), internal::priority_tag<2>()); ++} ++ ++// Implementation of C++20's std::ranges::iterator_t. ++// ++// Reference: https://wg21.link/ranges.syn#:~:text=iterator_t ++template ++using iterator_t = decltype(ranges::begin(std::declval())); ++ ++// Implementation of C++20's std::ranges::range_value_t. ++// ++// Reference: https://wg21.link/ranges.syn#:~:text=range_value_t ++template ++using range_value_t = iter_value_t>; ++ ++} // 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" @@ -939,9 +6087,9 @@ diff -up chromium-86.0.4240.75/base/sampling_heap_profiler/poisson_allocation_sa DCHECK(it != observers_.end()); observers_.erase(it); g_running = !observers_.empty(); -diff -up chromium-86.0.4240.75/base/scoped_observer.h.a61fb57e chromium-86.0.4240.75/base/scoped_observer.h ---- chromium-86.0.4240.75/base/scoped_observer.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/scoped_observer.h 2020-10-21 16:47:44.604936721 -0400 +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 @@ -964,9 +6112,9 @@ diff -up chromium-86.0.4240.75/base/scoped_observer.h.a61fb57e chromium-86.0.424 DCHECK(it != sources_.end()); sources_.erase(it); (source->*RemoveObsFn)(observer_); -diff -up chromium-86.0.4240.75/base/strings/abseil_string_conversions.cc.a61fb57e chromium-86.0.4240.75/base/strings/abseil_string_conversions.cc ---- chromium-86.0.4240.75/base/strings/abseil_string_conversions.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/strings/abseil_string_conversions.cc 2020-10-21 16:38:29.007091366 -0400 +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" @@ -998,9 +6146,9 @@ diff -up chromium-86.0.4240.75/base/strings/abseil_string_conversions.cc.a61fb57 return pieces; } -diff -up chromium-86.0.4240.75/base/strings/string_util_internal.h.a61fb57e chromium-86.0.4240.75/base/strings/string_util_internal.h ---- chromium-86.0.4240.75/base/strings/string_util_internal.h.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/strings/string_util_internal.h 2020-10-21 16:38:29.007091366 -0400 +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" @@ -1019,9 +6167,9 @@ diff -up chromium-86.0.4240.75/base/strings/string_util_internal.h.a61fb57e chro r_offset); } if (index < substitutions) -diff -up chromium-86.0.4240.75/base/synchronization/waitable_event_posix.cc.a61fb57e chromium-86.0.4240.75/base/synchronization/waitable_event_posix.cc ---- chromium-86.0.4240.75/base/synchronization/waitable_event_posix.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/synchronization/waitable_event_posix.cc 2020-10-21 16:38:29.008091375 -0400 +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 @@ -1046,9 +6194,9 @@ diff -up chromium-86.0.4240.75/base/synchronization/waitable_event_posix.cc.a61f // 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.75/base/task/common/checked_lock_impl.cc.a61fb57e chromium-86.0.4240.75/base/task/common/checked_lock_impl.cc ---- chromium-86.0.4240.75/base/task/common/checked_lock_impl.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/task/common/checked_lock_impl.cc 2020-10-21 16:38:29.008091375 -0400 +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" @@ -1073,9 +6221,9 @@ diff -up chromium-86.0.4240.75/base/task/common/checked_lock_impl.cc.a61fb57e ch DCHECK(iter_at_lock != acquired_locks->end()); acquired_locks->erase(iter_at_lock); } -diff -up chromium-86.0.4240.75/base/task/common/operations_controller_unittest.cc.a61fb57e chromium-86.0.4240.75/base/task/common/operations_controller_unittest.cc ---- chromium-86.0.4240.75/base/task/common/operations_controller_unittest.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/task/common/operations_controller_unittest.cc 2020-10-21 16:38:29.008091375 -0400 +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 #include @@ -1094,9 +6242,9 @@ diff -up chromium-86.0.4240.75/base/task/common/operations_controller_unittest.c break; } } -diff -up chromium-86.0.4240.75/base/task/common/task_annotator.cc.a61fb57e chromium-86.0.4240.75/base/task/common/task_annotator.cc ---- chromium-86.0.4240.75/base/task/common/task_annotator.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/task/common/task_annotator.cc 2020-10-21 16:48:17.376221810 -0400 +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" @@ -1115,9 +6263,9 @@ diff -up chromium-86.0.4240.75/base/task/common/task_annotator.cc.a61fb57e chrom task_backtrace[kStackTaskTraceSnapshotSize - 2] = reinterpret_cast(pending_task->ipc_hash); debug::Alias(&task_backtrace); -diff -up chromium-86.0.4240.75/base/task/sequence_manager/sequence_manager_impl.cc.a61fb57e chromium-86.0.4240.75/base/task/sequence_manager/sequence_manager_impl.cc ---- chromium-86.0.4240.75/base/task/sequence_manager/sequence_manager_impl.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/task/sequence_manager/sequence_manager_impl.cc 2020-10-21 16:38:29.008091375 -0400 +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" @@ -1136,9 +6284,9 @@ diff -up chromium-86.0.4240.75/base/task/sequence_manager/sequence_manager_impl. size_t length = 0; while (length < task_trace.size() && task_trace[length]) ++length; -diff -up chromium-86.0.4240.75/base/task/sequence_manager/task_queue_impl.cc.a61fb57e chromium-86.0.4240.75/base/task/sequence_manager/task_queue_impl.cc ---- chromium-86.0.4240.75/base/task/sequence_manager/task_queue_impl.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/task/sequence_manager/task_queue_impl.cc 2020-10-21 16:38:29.008091375 -0400 +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 @@ -1156,9 +6304,9 @@ diff -up chromium-86.0.4240.75/base/task/sequence_manager/task_queue_impl.cc.a61 } Value TaskQueueImpl::DelayedIncomingQueue::AsValue(TimeTicks now) const { -diff -up chromium-86.0.4240.75/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc.a61fb57e chromium-86.0.4240.75/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc ---- chromium-86.0.4240.75/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc 2020-10-21 16:38:29.009091383 -0400 +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" @@ -1184,9 +6332,9 @@ diff -up chromium-86.0.4240.75/base/task/thread_pool/pooled_single_thread_task_r DCHECK(worker_iter != workers_.end()); worker_to_destroy = std::move(*worker_iter); workers_.erase(worker_iter); -diff -up chromium-86.0.4240.75/base/task/thread_pool/thread_group_impl.cc.a61fb57e chromium-86.0.4240.75/base/task/thread_pool/thread_group_impl.cc ---- chromium-86.0.4240.75/base/task/thread_pool/thread_group_impl.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/task/thread_pool/thread_group_impl.cc 2020-10-21 16:38:29.009091383 -0400 +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" @@ -1220,9 +6368,9 @@ diff -up chromium-86.0.4240.75/base/task/thread_pool/thread_group_impl.cc.a61fb5 DCHECK(worker_iter != outer_->workers_.end()); outer_->workers_.erase(worker_iter); } -diff -up chromium-86.0.4240.75/base/task/thread_pool/worker_thread_stack.cc.a61fb57e chromium-86.0.4240.75/base/task/thread_pool/worker_thread_stack.cc ---- chromium-86.0.4240.75/base/task/thread_pool/worker_thread_stack.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/task/thread_pool/worker_thread_stack.cc 2020-10-21 16:38:29.009091383 -0400 +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" @@ -1243,9 +6391,9 @@ diff -up chromium-86.0.4240.75/base/task/thread_pool/worker_thread_stack.cc.a61f DCHECK(it != stack_.end()); DCHECK_NE(TimeTicks(), (*it)->GetLastUsedTime()); stack_.erase(it); -diff -up chromium-86.0.4240.75/base/test/launcher/test_launcher.cc.a61fb57e chromium-86.0.4240.75/base/test/launcher/test_launcher.cc ---- chromium-86.0.4240.75/base/test/launcher/test_launcher.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/test/launcher/test_launcher.cc 2020-10-21 16:38:29.009091383 -0400 +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" @@ -1272,9 +6420,9 @@ diff -up chromium-86.0.4240.75/base/test/launcher/test_launcher.cc.a61fb57e chro fprintf(stdout, "Randomizing with seed %u\n", shuffle_seed); fflush(stdout); -diff -up chromium-86.0.4240.75/base/test/scoped_feature_list.cc.a61fb57e chromium-86.0.4240.75/base/test/scoped_feature_list.cc ---- chromium-86.0.4240.75/base/test/scoped_feature_list.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/test/scoped_feature_list.cc 2020-10-21 16:38:29.009091383 -0400 +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" @@ -1304,9 +6452,9 @@ diff -up chromium-86.0.4240.75/base/test/scoped_feature_list.cc.a61fb57e chromiu return iter != feature_vector.end(); } -diff -up chromium-86.0.4240.75/base/test/trace_event_analyzer.cc.a61fb57e chromium-86.0.4240.75/base/test/trace_event_analyzer.cc ---- chromium-86.0.4240.75/base/test/trace_event_analyzer.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/test/trace_event_analyzer.cc 2020-10-21 16:38:29.010091392 -0400 +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" @@ -1344,9 +6492,9 @@ diff -up chromium-86.0.4240.75/base/test/trace_event_analyzer.cc.a61fb57e chromi stats->mean_us = delta_sum / static_cast(num_deltas); double sum_mean_offsets_squared = 0.0; -diff -up chromium-86.0.4240.75/base/threading/hang_watcher.cc.a61fb57e chromium-86.0.4240.75/base/threading/hang_watcher.cc ---- chromium-86.0.4240.75/base/threading/hang_watcher.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/threading/hang_watcher.cc 2020-10-21 16:38:29.010091392 -0400 +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" @@ -1408,9 +6556,9 @@ diff -up chromium-86.0.4240.75/base/threading/hang_watcher.cc.a61fb57e chromium- // Thread should be registered to get unregistered. DCHECK(it != watch_states_.end()); -diff -up chromium-86.0.4240.75/base/trace_event/trace_log.cc.a61fb57e chromium-86.0.4240.75/base/trace_event/trace_log.cc ---- chromium-86.0.4240.75/base/trace_event/trace_log.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/trace_event/trace_log.cc 2020-10-21 16:38:29.010091392 -0400 +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" @@ -1437,9 +6585,9 @@ diff -up chromium-86.0.4240.75/base/trace_event/trace_log.cc.a61fb57e chromium-8 enabled_state_observers_.end()); } -diff -up chromium-86.0.4240.75/base/values.cc.a61fb57e chromium-86.0.4240.75/base/values.cc ---- chromium-86.0.4240.75/base/values.cc.a61fb57e 2020-10-07 12:38:34.000000000 -0400 -+++ chromium-86.0.4240.75/base/values.cc 2020-10-21 16:38:29.010091392 -0400 +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 @@ -1474,9 +6622,9 @@ diff -up chromium-86.0.4240.75/base/values.cc.a61fb57e chromium-86.0.4240.75/bas } void ListValue::Swap(ListValue* other) { -diff -up chromium-86.0.4240.75/content/public/browser/content_browser_client.cc.a61fb57e chromium-86.0.4240.75/content/public/browser/content_browser_client.cc ---- chromium-86.0.4240.75/content/public/browser/content_browser_client.cc.a61fb57e 2020-10-21 16:38:29.011091401 -0400 -+++ chromium-86.0.4240.75/content/public/browser/content_browser_client.cc 2020-10-21 16:48:43.858452175 -0400 +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 @@ -1486,9 +6634,9 @@ diff -up chromium-86.0.4240.75/content/public/browser/content_browser_client.cc. #include -diff -up chromium-86.0.4240.75/third_party/blink/renderer/core/dom/document.cc.a61fb57e chromium-86.0.4240.75/third_party/blink/renderer/core/dom/document.cc ---- chromium-86.0.4240.75/third_party/blink/renderer/core/dom/document.cc.a61fb57e 2020-10-21 16:38:29.013091419 -0400 -+++ chromium-86.0.4240.75/third_party/blink/renderer/core/dom/document.cc 2020-10-21 16:49:03.209620502 -0400 +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 From d6246f859175660eb97edf9514ffa8249844024e Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Wed, 21 Oct 2020 18:27:58 -0400 Subject: [PATCH 09/10] focused backporting then --- chromium-86-use-range-based-algorithms.patch | 6641 +----------------- chromium.spec | 1 + 2 files changed, 8 insertions(+), 6634 deletions(-) diff --git a/chromium-86-use-range-based-algorithms.patch b/chromium-86-use-range-based-algorithms.patch index e9ea3f30..56a7216e 100644 --- a/chromium-86-use-range-based-algorithms.patch +++ b/chromium-86-use-range-based-algorithms.patch @@ -1,6648 +1,21 @@ -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 - #include - #include - #include -@@ -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 - #include - - #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 - #include - -+#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 vector = {3, 1, 4, 2, 5}; - CheckedContiguousRange> 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 - size_t Erase(circular_deque& 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& containe - - template - size_t EraseIf(circular_deque& 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 - - #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 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 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 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 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 - #include - -+#include "base/ranges/algorithm.h" - #include "base/stl_util.h" - #include "base/template_util.h" - -@@ -753,11 +754,10 @@ template ::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_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 -@@ -904,7 +904,7 @@ auto flat_tree& 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& - 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 - #include - -+#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 - --#include - #include - #include - #include -@@ -14,6 +13,7 @@ - #include - - #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 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 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 - #include - #include - -+#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(foo1)); -+ auto iter = ranges::find_if(v, UniquePtrMatcher(foo1)); - ASSERT_TRUE(iter != v.end()); - EXPECT_EQ(foo1, iter->get()); - } - - { -- auto iter = std::find_if(v.begin(), v.end(), UniquePtrMatcher(foo2)); -+ auto iter = ranges::find_if(v, UniquePtrMatcher(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(foo1)); -+ auto iter = ranges::find_if(v, UniquePtrMatcher(foo1)); - ASSERT_TRUE(iter != v.end()); - EXPECT_EQ(foo1, iter->get()); - } - - { -- auto iter = std::find_if(v.begin(), v.end(), -- UniquePtrMatcher(foo2)); -+ auto iter = ranges::find_if(v, UniquePtrMatcher(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()); - } -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 - #include - - #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 - #endif // OS_ANDROID - --#include - #include - #include - -@@ -55,8 +55,7 @@ TaskTrace::TaskTrace() { - return; - std::array 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 - --#include - #include - #include - -@@ -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 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 - #include --#include - #include - #include - - #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 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 - #include - -+#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" +diff -up chromium-86.0.4240.111/base/strings/string_util_internal.h.ranges chromium-86.0.4240.111/base/strings/string_util_internal.h +--- chromium-86.0.4240.111/base/strings/string_util_internal.h.ranges 2020-10-21 18:25:31.939001816 -0400 ++++ chromium-86.0.4240.111/base/strings/string_util_internal.h 2020-10-21 18:26:36.686485073 -0400 +@@ -9,6 +9,7 @@ #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 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 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(addr); -- }); -+ auto it = ranges::find_if( -+ regions, [addr](const base::debug::MappedMemoryRegion& region) { -+ return region.start == reinterpret_cast(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 - --#include - #include - - #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 read_span = read_mapping_.GetMemoryAsSpan(); - 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 read_span_2 = read_mapping_.GetMemoryAsSpan(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 - #include - --#include - #include - #include - -@@ -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 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& 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& 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& 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& 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 -+#include "base/ranges/algorithm.h" - - namespace base { - -@@ -91,8 +91,7 @@ Optional 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 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 - #include - #include + #include "base/third_party/icu/icu_utf.h" ++#include "base/util/ranges/algorithm.h" -+#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 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) { -- return unwinder->CanUnwindFrom(stack.back()); -- }); -+ auto unwinder = ranges::find_if( -+ unwinders, [&stack](const std::unique_ptr& 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 - #include - --#include - #include - #include - #include -@@ -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>& infos) { - // Map unique_ptrs to something that WaitMany can accept. - std::vector sampling_completed_rawptrs(infos.size()); -- std::transform(infos.begin(), infos.end(), sampling_completed_rawptrs.begin(), -- [](const std::unique_ptr& info) { -- return &info.get()->completed; -- }); -+ ranges::transform(infos, sampling_completed_rawptrs.begin(), -+ [](const std::unique_ptr& 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 -+#include -+#include -+#include -+#include -+ -+#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 -+constexpr auto ProjectedUnaryPredicate(Pred& pred, Proj& proj) noexcept { -+ return [&pred, &proj](auto&& arg) -> bool { -+ return base::invoke(pred, -+ base::invoke(proj, std::forward(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, Proj1>, -+// projected, Proj2>> -+// -+// Ensures that the return type of `invoke(pred, ...)` is convertible to bool. -+template -+class BinaryPredicateProjector { -+ public: -+ constexpr BinaryPredicateProjector(Pred& pred, Proj1& proj1, Proj2& proj2) -+ : pred_(pred), proj1_(proj1), proj2_(proj2) {} -+ -+ private: -+ template -+ using InvokeResult = invoke_result_t, -+ invoke_result_t>; -+ -+ template > -+ constexpr std::pair GetProjs(priority_tag<3>) const { -+ return {proj1_, proj2_}; -+ } -+ -+ template , -+ typename = InvokeResult> -+ constexpr std::pair GetProjs(priority_tag<2>) const { -+ return {proj2_, proj1_}; -+ } -+ -+ template , -+ typename = InvokeResult> -+ constexpr std::pair GetProjs(priority_tag<1>) const { -+ return {proj1_, proj1_}; -+ } -+ -+ template , -+ typename = InvokeResult> -+ constexpr std::pair GetProjs(priority_tag<0>) const { -+ return {proj2_, proj2_}; -+ } -+ -+ public: -+ template -+ constexpr bool operator()(T&& lhs, U&& rhs) const { -+ auto projs = GetProjs(priority_tag<3>()); -+ return base::invoke(pred_, base::invoke(projs.first, std::forward(lhs)), -+ base::invoke(projs.second, std::forward(rhs))); -+ } -+ -+ private: -+ Pred& pred_; -+ Proj1& proj1_; -+ Proj2& proj2_; -+}; -+ -+// Small wrappers around BinaryPredicateProjector to make the calling side more -+// readable. -+template -+constexpr auto ProjectedBinaryPredicate(Pred& pred, -+ Proj1& proj1, -+ Proj2& proj2) noexcept { -+ return BinaryPredicateProjector(pred, proj1, proj2); -+} -+ -+template -+constexpr auto PermutedProjectedBinaryPredicate(Pred& pred, -+ Proj1& proj1, -+ Proj2& proj2) noexcept { -+ return BinaryPredicateProjector(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 = decltype(std::declval()++)> -+using iterator_category_t = -+ typename std::iterator_traits::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 -+using range_category_t = iterator_category_t>; -+ -+} // 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 -+struct in_fun_result { -+ /* [[no_unique_address]] */ I in; -+ /* [[no_unique_address]] */ F fun; -+ -+ template {} && -+ std::is_convertible{}>> -+ constexpr operator in_fun_result() const& { -+ return {in, fun}; -+ } -+ -+ template {} && -+ std::is_convertible{}>> -+ constexpr operator in_fun_result() && { -+ 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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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 -+using for_each_result = in_fun_result; -+ -+// 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 > -+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{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 > -+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 -+using for_each_n_result = in_fun_result; -+ -+// 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 > -+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{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 > -+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(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 > -+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 > -+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 > -+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 > -+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 > -+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 = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, 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 = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, 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 > -+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 > -+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 > -+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(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 > -+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 > -+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 > -+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 = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, 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 = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, 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 = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, 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 = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, 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 > -+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 > -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::range_category_t> -+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 = internal::iterator_category_t, -+ typename = indirect_result_t>> -+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(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 = internal::iterator_category_t, -+ typename = indirect_result_t, 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 = internal::iterator_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>> -+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(lhs)), -+ base::invoke(proj2, std::forward(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 = internal::range_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, 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 > -+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(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 > -+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 > -+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 > -+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 = internal::iterator_category_t> -+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(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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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(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 > -+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 > -+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 > -+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 = internal::iterator_category_t> -+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(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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 > -+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 > -+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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+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 > -+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 > -+constexpr auto rotate(Range&& range, iterator_t 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 = internal::iterator_category_t> -+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 = internal::iterator_category_t> -+constexpr auto rotate_copy(Range&& range, -+ iterator_t 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` -+// 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 > -+constexpr auto shuffle(RandomAccessIterator first, -+ RandomAccessIterator last, -+ UniformRandomBitGenerator&& g) { -+ std::shuffle(first, last, std::forward(g)); -+ return last; -+} -+ -+// Preconditions: The type `std::remove_reference_t` -+// 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 > -+constexpr auto shuffle(Range&& range, UniformRandomBitGenerator&& g) { -+ return ranges::shuffle(ranges::begin(range), ranges::end(range), -+ std::forward(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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, Proj>>> -+constexpr auto partial_sort(Range&& range, -+ iterator_t 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 = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, Proj2>>, -+ typename = indirect_result_t, Proj2>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, Proj>>> -+constexpr auto nth_element(Range&& range, -+ iterator_t 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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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 > -+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 = internal::iterator_category_t, -+ typename = internal::iterator_category_t> -+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 = internal::iterator_category_t, -+ typename = internal::iterator_category_t> -+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 > -+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 > -+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 = internal::iterator_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, Proj2>>, -+ typename = indirect_result_t, Proj2>, -+ projected, 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 > -+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 > -+constexpr auto inplace_merge(Range&& range, -+ iterator_t 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 = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, Proj2>>, -+ typename = indirect_result_t, Proj2>, -+ projected, 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 = internal::iterator_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, Proj2>>, -+ typename = indirect_result_t, Proj2>, -+ projected, 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 = internal::iterator_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, Proj2>>, -+ typename = indirect_result_t, Proj2>, -+ projected, 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 = internal::iterator_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, Proj2>>, -+ typename = indirect_result_t, Proj2>, -+ projected, 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 = internal::iterator_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = internal::iterator_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, Proj2>>, -+ typename = indirect_result_t, Proj2>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 -+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 -+constexpr T min(std::initializer_list 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 > -+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 -+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 -+constexpr T max(std::initializer_list 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 > -+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 -+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 -+constexpr auto minmax(std::initializer_list ilist, -+ Comp comp = {}, -+ Proj proj = {}) { -+ auto it = -+ std::minmax_element(ranges::begin(ilist), ranges::end(ilist), -+ internal::ProjectedBinaryPredicate(comp, proj, proj)); -+ return std::pair{*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 > -+constexpr auto minmax(Range&& range, Comp comp = {}, Proj proj = {}) { -+ using T = range_value_t; -+ auto it = -+ std::minmax_element(ranges::begin(range), ranges::end(range), -+ internal::ProjectedBinaryPredicate(comp, proj, proj)); -+ return std::pair{*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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 -+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 = internal::iterator_category_t, -+ typename = indirect_result_t, -+ projected>, -+ typename = indirect_result_t, -+ projected>> -+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 = internal::range_category_t, -+ typename = indirect_result_t, Proj1>, -+ projected, Proj2>>, -+ typename = indirect_result_t, Proj2>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 = indirect_result_t, -+ projected>> -+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 = indirect_result_t, Proj>, -+ projected, 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 -+#include -+#include -+ -+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 -+#include -+#include -+#include -+ -+#include "base/template_util.h" -+ -+namespace base { -+ -+namespace internal { -+ -+// Overload for C array. -+template -+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 -+constexpr T* begin(std::array& array, priority_tag<2> tag) { -+ return const_cast(begin(const_cast&>(array), tag)); -+} -+ -+// Overload for const std::array. Required since std::array::begin is not -+// constexpr prior to C++17. -+template -+constexpr const T* begin(const std::array& array, priority_tag<2>) { -+ return N != 0 ? &array[0] : nullptr; -+} -+ -+// Generic container overload. -+template -+constexpr auto begin(Range&& range, priority_tag<1>) -+ -> decltype(std::forward(range).begin()) { -+ return std::forward(range).begin(); -+} -+ -+// Overload for free begin() function. -+template -+constexpr auto begin(Range&& range, priority_tag<0>) -+ -> decltype(begin(std::forward(range))) { -+ return begin(std::forward(range)); -+} -+ -+// Overload for C array. -+template -+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 -+constexpr T* end(std::array& array, priority_tag<2> tag) { -+ return const_cast(end(const_cast&>(array), tag)); -+} -+ -+// Overload for const std::array. Required since std::array::end is not -+// constexpr prior to C++17. -+template -+constexpr const T* end(const std::array& array, priority_tag<2>) { -+ return N != 0 ? (&array[0]) + N : nullptr; -+} -+ -+// Generic container overload. -+template -+constexpr auto end(Range&& range, priority_tag<1>) -+ -> decltype(std::forward(range).end()) { -+ return std::forward(range).end(); -+} -+ -+// Overload for free end() function. -+template -+constexpr auto end(Range&& range, priority_tag<0>) -+ -> decltype(end(std::forward(range))) { -+ return end(std::forward(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 -+constexpr auto begin(Range&& range) noexcept -+ -> decltype(internal::begin(std::forward(range), -+ internal::priority_tag<2>())) { -+ return internal::begin(std::forward(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 -+constexpr auto end(Range&& range) noexcept -+ -> decltype(internal::end(std::forward(range), -+ internal::priority_tag<2>())) { -+ return internal::end(std::forward(range), internal::priority_tag<2>()); -+} -+ -+// Implementation of C++20's std::ranges::iterator_t. -+// -+// Reference: https://wg21.link/ranges.syn#:~:text=iterator_t -+template -+using iterator_t = decltype(ranges::begin(std::declval())); -+ -+// Implementation of C++20's std::ranges::range_value_t. -+// -+// Reference: https://wg21.link/ranges.syn#:~:text=range_value_t -+template -+using range_value_t = iter_value_t>; -+ -+} // 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 - #include - #include - #include -@@ -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 - --#include - #include - - #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 - #include - - #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 StringPiecesToStringViews( - span pieces) { - std::vector views(pieces.size()); -- std::transform(pieces.begin(), pieces.end(), views.begin(), -- &StringPieceToStringView); -+ ranges::transform(pieces, views.begin(), &StringPieceToStringView); - return views; - } - - std::vector StringViewsToStringPieces( - span views) { - std::vector 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(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), ++ util::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 - --#include - #include - #include - - #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 - #include - #include - - #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 - #include - -+#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(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(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 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 - - #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 - #include - #include - #include -@@ -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>& workers, - const WorkerThread* worker) { -- auto it = std::find_if(workers.begin(), workers.end(), -- [worker](const scoped_refptr& i) { -- return i.get() == worker; -- }); -+ auto it = -+ ranges::find_if(workers, [worker](const scoped_refptr& 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 -- - #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 - #include - #include - - #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& 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(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 - #include - #include - -@@ -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& 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& state) { -- return state.get() == current_hang_watch_state; -- }); -+ auto it = ranges::find_if( -+ watch_states_, -+ [current_hang_watch_state]( -+ const std::unique_ptr& 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 - #include - #include - #include -@@ -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 - --#include - #include - #include - #include -@@ -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 - -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 - #include diff --git a/chromium.spec b/chromium.spec index 08b7d050..abedb50b 100644 --- a/chromium.spec +++ b/chromium.spec @@ -276,6 +276,7 @@ Patch71: chromium-84.0.4147.125-aarch64-clearkeycdm-binutils-workaround.patch # https://github.com/chromium/chromium/commit/53478caee862624fc6d73516f8d64253854b146f Patch72: chromium-85.0.4183.102-invalid-end-CookieMonster-53478ca.patch # EL7 failed to compile without this, but it seems accurate for all branches +# just a bit taken from # https://github.com/chromium/chromium/commit/a61fb57edb75fcfe251af0e6f66820d13924ad62 Patch73: chromium-86-use-range-based-algorithms.patch From d61fe4879df4195ec52ec9c3aa9bdcd28ca2bad3 Mon Sep 17 00:00:00 2001 From: Tom Callaway Date: Sat, 24 Oct 2020 07:47:17 -0400 Subject: [PATCH 10/10] el7 fixes, hopefully, all we need for now --- chromium-86-use-range-based-algorithms.patch | 21 - ...el7-limit-nearby-sharing-to-chromeos.patch | 1135 +++++++++++++++++ chromium.spec | 10 +- 3 files changed, 1140 insertions(+), 26 deletions(-) delete mode 100644 chromium-86-use-range-based-algorithms.patch create mode 100644 chromium-86.0.4240.111-el7-limit-nearby-sharing-to-chromeos.patch diff --git a/chromium-86-use-range-based-algorithms.patch b/chromium-86-use-range-based-algorithms.patch deleted file mode 100644 index 56a7216e..00000000 --- a/chromium-86-use-range-based-algorithms.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up chromium-86.0.4240.111/base/strings/string_util_internal.h.ranges chromium-86.0.4240.111/base/strings/string_util_internal.h ---- chromium-86.0.4240.111/base/strings/string_util_internal.h.ranges 2020-10-21 18:25:31.939001816 -0400 -+++ chromium-86.0.4240.111/base/strings/string_util_internal.h 2020-10-21 18:26:36.686485073 -0400 -@@ -9,6 +9,7 @@ - #include "base/notreached.h" - #include "base/strings/string_piece.h" - #include "base/third_party/icu/icu_utf.h" -+#include "base/util/ranges/algorithm.h" - - namespace base { - -@@ -578,8 +579,7 @@ StringType DoReplaceStringPlaceholders( - ReplacementOffset r_offset(index, - static_cast(formatted.size())); - r_offsets.insert( -- std::upper_bound(r_offsets.begin(), r_offsets.end(), r_offset, -- &CompareParameter), -+ util::ranges::upper_bound(r_offsets, r_offset, &CompareParameter), - r_offset); - } - if (index < substitutions) diff --git a/chromium-86.0.4240.111-el7-limit-nearby-sharing-to-chromeos.patch b/chromium-86.0.4240.111-el7-limit-nearby-sharing-to-chromeos.patch new file mode 100644 index 00000000..13663a7e --- /dev/null +++ b/chromium-86.0.4240.111-el7-limit-nearby-sharing-to-chromeos.patch @@ -0,0 +1,1135 @@ +diff -up chromium-86.0.4240.111/chrome/browser/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/BUILD.gn.disable-nearby_sharing 2020-10-22 10:18:26.618372988 -0400 ++++ chromium-86.0.4240.111/chrome/browser/BUILD.gn 2020-10-22 10:18:25.065360685 -0400 +@@ -3378,64 +3378,6 @@ static_library("browser") { + "metrics/tab_stats_tracker.cc", + "metrics/tab_stats_tracker.h", + "metrics/tab_stats_tracker_delegate.h", +- "nearby_sharing/attachment_info.cc", +- "nearby_sharing/attachment_info.h", +- "nearby_sharing/constants.h", +- "nearby_sharing/fast_initiation_manager.cc", +- "nearby_sharing/fast_initiation_manager.h", +- "nearby_sharing/incoming_frames_reader.cc", +- "nearby_sharing/incoming_frames_reader.h", +- "nearby_sharing/incoming_share_target_info.cc", +- "nearby_sharing/incoming_share_target_info.h", +- "nearby_sharing/instantmessaging/constants.h", +- "nearby_sharing/instantmessaging/receive_messages_express.cc", +- "nearby_sharing/instantmessaging/receive_messages_express.h", +- "nearby_sharing/instantmessaging/send_message_express.cc", +- "nearby_sharing/instantmessaging/send_message_express.h", +- "nearby_sharing/instantmessaging/stream_parser.cc", +- "nearby_sharing/instantmessaging/stream_parser.h", +- "nearby_sharing/instantmessaging/token_fetcher.cc", +- "nearby_sharing/instantmessaging/token_fetcher.h", +- "nearby_sharing/nearby_confirmation_manager.cc", +- "nearby_sharing/nearby_confirmation_manager.h", +- "nearby_sharing/nearby_connection.h", +- "nearby_sharing/nearby_connection_impl.cc", +- "nearby_sharing/nearby_connection_impl.h", +- "nearby_sharing/nearby_connections_manager.h", +- "nearby_sharing/nearby_connections_manager_impl.cc", +- "nearby_sharing/nearby_connections_manager_impl.h", +- "nearby_sharing/nearby_notification_delegate.h", +- "nearby_sharing/nearby_notification_handler.cc", +- "nearby_sharing/nearby_notification_handler.h", +- "nearby_sharing/nearby_notification_manager.cc", +- "nearby_sharing/nearby_notification_manager.h", +- "nearby_sharing/nearby_per_session_discovery_manager.cc", +- "nearby_sharing/nearby_per_session_discovery_manager.h", +- "nearby_sharing/nearby_process_manager.cc", +- "nearby_sharing/nearby_process_manager.h", +- "nearby_sharing/nearby_share_settings.cc", +- "nearby_sharing/nearby_share_settings.h", +- "nearby_sharing/nearby_sharing_service.h", +- "nearby_sharing/nearby_sharing_service_factory.cc", +- "nearby_sharing/nearby_sharing_service_factory.h", +- "nearby_sharing/nearby_sharing_service_impl.cc", +- "nearby_sharing/nearby_sharing_service_impl.h", +- "nearby_sharing/outgoing_share_target_info.cc", +- "nearby_sharing/outgoing_share_target_info.h", +- "nearby_sharing/paired_key_verification_runner.cc", +- "nearby_sharing/paired_key_verification_runner.h", +- "nearby_sharing/share_target.cc", +- "nearby_sharing/share_target.h", +- "nearby_sharing/share_target_discovered_callback.h", +- "nearby_sharing/share_target_info.cc", +- "nearby_sharing/share_target_info.h", +- "nearby_sharing/transfer_metadata.cc", +- "nearby_sharing/transfer_metadata.h", +- "nearby_sharing/transfer_metadata_builder.cc", +- "nearby_sharing/transfer_metadata_builder.h", +- "nearby_sharing/transfer_update_callback.h", +- "nearby_sharing/webrtc_signaling_messenger.cc", +- "nearby_sharing/webrtc_signaling_messenger.h", + "notifications/notification_system_observer.cc", + "notifications/notification_system_observer.h", + "notifications/profile_notification.cc", +@@ -3824,17 +3766,6 @@ static_library("browser") { + "//chrome/app/vector_icons", + "//chrome/browser/media/kaleidoscope:kaleidoscope_resources", + "//chrome/browser/media/kaleidoscope/mojom", +- "//chrome/browser/nearby_sharing:share_target", +- "//chrome/browser/nearby_sharing/certificates", +- "//chrome/browser/nearby_sharing/client", +- "//chrome/browser/nearby_sharing/common", +- "//chrome/browser/nearby_sharing/contacts", +- "//chrome/browser/nearby_sharing/instantmessaging/proto", +- "//chrome/browser/nearby_sharing/local_device_data", +- "//chrome/browser/nearby_sharing/logging", +- "//chrome/browser/nearby_sharing/logging:util", +- "//chrome/browser/nearby_sharing/proto", +- "//chrome/browser/nearby_sharing/scheduling", + "//chrome/browser/policy:path_parser", + "//chrome/browser/profile_resetter:profile_reset_report_proto", + "//chrome/browser/resource_coordinator:intervention_policy_database_proto", +@@ -3990,6 +3921,64 @@ static_library("browser") { + "metrics/perf/random_selector.h", + "metrics/perf/windowed_incognito_observer.cc", + "metrics/perf/windowed_incognito_observer.h", ++ "nearby_sharing/attachment_info.cc", ++ "nearby_sharing/attachment_info.h", ++ "nearby_sharing/constants.h", ++ "nearby_sharing/fast_initiation_manager.cc", ++ "nearby_sharing/fast_initiation_manager.h", ++ "nearby_sharing/incoming_frames_reader.cc", ++ "nearby_sharing/incoming_frames_reader.h", ++ "nearby_sharing/incoming_share_target_info.cc", ++ "nearby_sharing/incoming_share_target_info.h", ++ "nearby_sharing/instantmessaging/constants.h", ++ "nearby_sharing/instantmessaging/receive_messages_express.cc", ++ "nearby_sharing/instantmessaging/receive_messages_express.h", ++ "nearby_sharing/instantmessaging/send_message_express.cc", ++ "nearby_sharing/instantmessaging/send_message_express.h", ++ "nearby_sharing/instantmessaging/stream_parser.cc", ++ "nearby_sharing/instantmessaging/stream_parser.h", ++ "nearby_sharing/instantmessaging/token_fetcher.cc", ++ "nearby_sharing/instantmessaging/token_fetcher.h", ++ "nearby_sharing/nearby_confirmation_manager.cc", ++ "nearby_sharing/nearby_confirmation_manager.h", ++ "nearby_sharing/nearby_connection.h", ++ "nearby_sharing/nearby_connection_impl.cc", ++ "nearby_sharing/nearby_connection_impl.h", ++ "nearby_sharing/nearby_connections_manager.h", ++ "nearby_sharing/nearby_connections_manager_impl.cc", ++ "nearby_sharing/nearby_connections_manager_impl.h", ++ "nearby_sharing/nearby_notification_delegate.h", ++ "nearby_sharing/nearby_notification_handler.cc", ++ "nearby_sharing/nearby_notification_handler.h", ++ "nearby_sharing/nearby_notification_manager.cc", ++ "nearby_sharing/nearby_notification_manager.h", ++ "nearby_sharing/nearby_per_session_discovery_manager.cc", ++ "nearby_sharing/nearby_per_session_discovery_manager.h", ++ "nearby_sharing/nearby_process_manager.cc", ++ "nearby_sharing/nearby_process_manager.h", ++ "nearby_sharing/nearby_share_settings.cc", ++ "nearby_sharing/nearby_share_settings.h", ++ "nearby_sharing/nearby_sharing_service.h", ++ "nearby_sharing/nearby_sharing_service_factory.cc", ++ "nearby_sharing/nearby_sharing_service_factory.h", ++ "nearby_sharing/nearby_sharing_service_impl.cc", ++ "nearby_sharing/nearby_sharing_service_impl.h", ++ "nearby_sharing/outgoing_share_target_info.cc", ++ "nearby_sharing/outgoing_share_target_info.h", ++ "nearby_sharing/paired_key_verification_runner.cc", ++ "nearby_sharing/paired_key_verification_runner.h", ++ "nearby_sharing/share_target.cc", ++ "nearby_sharing/share_target.h", ++ "nearby_sharing/share_target_discovered_callback.h", ++ "nearby_sharing/share_target_info.cc", ++ "nearby_sharing/share_target_info.h", ++ "nearby_sharing/transfer_metadata.cc", ++ "nearby_sharing/transfer_metadata.h", ++ "nearby_sharing/transfer_metadata_builder.cc", ++ "nearby_sharing/transfer_metadata_builder.h", ++ "nearby_sharing/transfer_update_callback.h", ++ "nearby_sharing/webrtc_signaling_messenger.cc", ++ "nearby_sharing/webrtc_signaling_messenger.h", + "notifications/arc_application_notifier_controller.cc", + "notifications/arc_application_notifier_controller.h", + "notifications/chrome_ash_message_center_client.cc", +@@ -4051,6 +4040,17 @@ static_library("browser") { + "//ash/public/cpp", + "//ash/public/cpp/external_arc", + "//chrome/browser/chromeos", ++ "//chrome/browser/nearby_sharing/common", ++ "//chrome/browser/nearby_sharing:share_target", ++ "//chrome/browser/nearby_sharing/certificates", ++ "//chrome/browser/nearby_sharing/client", ++ "//chrome/browser/nearby_sharing/contacts", ++ "//chrome/browser/nearby_sharing/instantmessaging/proto", ++ "//chrome/browser/nearby_sharing/local_device_data", ++ "//chrome/browser/nearby_sharing/logging", ++ "//chrome/browser/nearby_sharing/logging:util", ++ "//chrome/browser/nearby_sharing/proto", ++ "//chrome/browser/nearby_sharing/scheduling", + "//chromeos/components/account_manager", + "//chromeos/components/cdm_factory_daemon:cdm_factory_daemon_browser", + "//chromeos/components/quick_answers", +diff -up chromium-86.0.4240.111/chrome/browser/extensions/api/settings_private/prefs_util.cc.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/extensions/api/settings_private/prefs_util.cc +--- chromium-86.0.4240.111/chrome/browser/extensions/api/settings_private/prefs_util.cc.disable-nearby_sharing 2020-10-22 10:21:29.276819990 -0400 ++++ chromium-86.0.4240.111/chrome/browser/extensions/api/settings_private/prefs_util.cc 2020-10-22 10:22:22.905244833 -0400 +@@ -305,6 +305,7 @@ const PrefsUtil::TypedPrefMap& PrefsUtil + settings_api::PrefType::PREF_TYPE_DICTIONARY; + #endif + ++#if defined(OS_CHROMEOS) + // Nearby Share. + (*s_whitelist)[::prefs::kNearbySharingEnabledPrefName] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; +@@ -314,6 +315,7 @@ const PrefsUtil::TypedPrefMap& PrefsUtil + settings_api::PrefType::PREF_TYPE_STRING; + (*s_whitelist)[::prefs::kNearbySharingDataUsageName] = + settings_api::PrefType::PREF_TYPE_NUMBER; ++#endif + + // Search page. + (*s_whitelist)[DefaultSearchManager::kDefaultSearchProviderDataPrefName] = +diff -up chromium-86.0.4240.111/chrome/browser/extensions/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/extensions/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/extensions/BUILD.gn.disable-nearby_sharing 2020-10-22 10:20:10.002191986 -0400 ++++ chromium-86.0.4240.111/chrome/browser/extensions/BUILD.gn 2020-10-22 10:21:10.586671928 -0400 +@@ -774,7 +774,6 @@ static_library("extensions") { + "//chrome/browser/image_decoder", + "//chrome/browser/media/router", + "//chrome/browser/media/router/discovery", +- "//chrome/browser/nearby_sharing/common", + "//chrome/browser/resource_coordinator:intervention_policy_database_proto", + "//chrome/browser/resource_coordinator:mojo_bindings", + "//chrome/browser/safe_browsing", +@@ -1023,6 +1022,7 @@ static_library("extensions") { + "//ash/keyboard/ui:resources_grit_grit", + "//ash/public/cpp", + "//chrome/browser/chromeos/crostini:crostini_installer_types_mojom", ++ "//chrome/browser/nearby_sharing/common", + "//chrome/browser/ui/webui/settings/chromeos/constants:mojom", + "//chromeos", + "//chromeos/attestation", +diff -up chromium-86.0.4240.111/chrome/browser/nearby_sharing/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/nearby_sharing/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/nearby_sharing/BUILD.gn.disable-nearby_sharing 2020-10-22 10:22:35.857347439 -0400 ++++ chromium-86.0.4240.111/chrome/browser/nearby_sharing/BUILD.gn 2020-10-22 10:22:53.364486129 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + source_set("share_target") { + sources = [ + "attachment.cc", +diff -up chromium-86.0.4240.111/chrome/browser/nearby_sharing/certificates/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/nearby_sharing/certificates/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/nearby_sharing/certificates/BUILD.gn.disable-nearby_sharing 2020-10-22 10:23:11.225627627 -0400 ++++ chromium-86.0.4240.111/chrome/browser/nearby_sharing/certificates/BUILD.gn 2020-10-22 10:23:23.972728611 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + source_set("certificates") { + sources = [ + "common.cc", +diff -up chromium-86.0.4240.111/chrome/browser/nearby_sharing/client/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/nearby_sharing/client/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/nearby_sharing/client/BUILD.gn.disable-nearby_sharing 2020-10-22 10:23:38.273841904 -0400 ++++ chromium-86.0.4240.111/chrome/browser/nearby_sharing/client/BUILD.gn 2020-10-22 10:23:51.980950491 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + source_set("client") { + sources = [ + "nearby_share_api_call_flow.h", +diff -up chromium-86.0.4240.111/chrome/browser/nearby_sharing/common/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/nearby_sharing/common/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/nearby_sharing/common/BUILD.gn.disable-nearby_sharing 2020-10-22 10:24:03.625042734 -0400 ++++ chromium-86.0.4240.111/chrome/browser/nearby_sharing/common/BUILD.gn 2020-10-22 10:24:19.347167284 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + source_set("common") { + sources = [ + "nearby_share_enums.h", +diff -up chromium-86.0.4240.111/chrome/browser/nearby_sharing/contacts/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/nearby_sharing/contacts/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/nearby_sharing/contacts/BUILD.gn.disable-nearby_sharing 2020-10-22 10:24:35.969298963 -0400 ++++ chromium-86.0.4240.111/chrome/browser/nearby_sharing/contacts/BUILD.gn 2020-10-22 10:24:47.991405762 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + source_set("contacts") { + sources = [ + "nearby_share_contact_manager.cc", +diff -up chromium-86.0.4240.111/chrome/browser/nearby_sharing/local_device_data/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/nearby_sharing/local_device_data/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/nearby_sharing/local_device_data/BUILD.gn.disable-nearby_sharing 2020-10-22 10:25:01.904532442 -0400 ++++ chromium-86.0.4240.111/chrome/browser/nearby_sharing/local_device_data/BUILD.gn 2020-10-22 10:25:14.379646038 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + source_set("local_device_data") { + sources = [ + "nearby_share_device_data_updater.cc", +diff -up chromium-86.0.4240.111/chrome/browser/nearby_sharing/logging/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/nearby_sharing/logging/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/nearby_sharing/logging/BUILD.gn.disable-nearby_sharing 2020-10-22 10:25:27.194762726 -0400 ++++ chromium-86.0.4240.111/chrome/browser/nearby_sharing/logging/BUILD.gn 2020-10-22 10:25:40.191881068 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + source_set("logging") { + sources = [ + "log_buffer.cc", +diff -up chromium-86.0.4240.111/chrome/browser/nearby_sharing/proto/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/nearby_sharing/proto/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/nearby_sharing/proto/BUILD.gn.disable-nearby_sharing 2020-10-22 10:26:17.899224400 -0400 ++++ chromium-86.0.4240.111/chrome/browser/nearby_sharing/proto/BUILD.gn 2020-10-22 10:26:32.540357709 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + import("//third_party/protobuf/proto_library.gni") + + proto_library("proto") { +diff -up chromium-86.0.4240.111/chrome/browser/nearby_sharing/scheduling/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/nearby_sharing/scheduling/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/nearby_sharing/scheduling/BUILD.gn.disable-nearby_sharing 2020-10-22 10:26:49.726514190 -0400 ++++ chromium-86.0.4240.111/chrome/browser/nearby_sharing/scheduling/BUILD.gn 2020-10-22 10:27:05.204655124 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + source_set("scheduling") { + sources = [ + "nearby_share_expiration_scheduler.cc", +diff -up chromium-86.0.4240.111/chrome/browser/notifications/notification_display_service_impl.cc.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/notifications/notification_display_service_impl.cc +--- chromium-86.0.4240.111/chrome/browser/notifications/notification_display_service_impl.cc.disable-nearby_sharing 2020-10-22 10:27:31.529894851 -0400 ++++ chromium-86.0.4240.111/chrome/browser/notifications/notification_display_service_impl.cc 2020-10-22 10:28:43.622551281 -0400 +@@ -38,11 +38,14 @@ + #endif + + #if defined(OS_LINUX) || defined(OS_MAC) || defined(OS_WIN) +-#include "chrome/browser/nearby_sharing/nearby_notification_handler.h" + #include "chrome/browser/send_tab_to_self/desktop_notification_handler.h" + #include "chrome/browser/sharing/sharing_notification_handler.h" + #endif + ++#if defined(OS_CHROMEOS) ++#include "chrome/browser/nearby_sharing/nearby_notification_handler.h" ++#endif ++ + #if defined(OS_WIN) + #include "base/strings/utf_string_conversions.h" + #include "chrome/browser/notifications/notification_platform_bridge_win.h" +@@ -169,7 +172,9 @@ NotificationDisplayServiceImpl::Notifica + std::make_unique()); + AddNotificationHandler(NotificationHandler::Type::ANNOUNCEMENT, + std::make_unique()); ++#endif + ++#if defined(OS_CHROMEOS) + if (base::FeatureList::IsEnabled(features::kNearbySharing)) { + AddNotificationHandler(NotificationHandler::Type::NEARBY_SHARE, + std::make_unique()); +diff -up chromium-86.0.4240.111/chrome/browser/policy/configuration_policy_handler_list_factory.cc.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/policy/configuration_policy_handler_list_factory.cc +--- chromium-86.0.4240.111/chrome/browser/policy/configuration_policy_handler_list_factory.cc.disable-nearby_sharing 2020-10-22 10:29:00.985709391 -0400 ++++ chromium-86.0.4240.111/chrome/browser/policy/configuration_policy_handler_list_factory.cc 2020-10-22 10:31:05.720845193 -0400 +@@ -17,7 +17,6 @@ + #include "base/values.h" + #include "build/branding_buildflags.h" + #include "build/build_config.h" +-#include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h" + #include "chrome/browser/net/disk_cache_dir_policy_handler.h" + #include "chrome/browser/net/referrer_policy_policy_handler.h" + #include "chrome/browser/net/secure_dns_policy_handler.h" +@@ -120,6 +119,7 @@ + #include "chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h" + #include "chrome/browser/chromeos/policy/secondary_google_account_signin_policy_handler.h" + #include "chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.h" ++#include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h" + #include "chrome/browser/policy/default_geolocation_policy_handler.h" + #include "chrome/common/chrome_features.h" + #include "chromeos/constants/chromeos_pref_names.h" +@@ -1525,8 +1525,6 @@ std::unique_ptrAddHandler( + std::make_unique()); +- handlers->AddHandler(std::make_unique( +- key::kNearbyShareAllowed, prefs::kNearbySharingEnabledPrefName)); + handlers->AddHandler(std::make_unique()); + handlers->AddHandler( + std::make_unique(chrome_schema)); +@@ -1846,6 +1844,8 @@ std::unique_ptr( + key::kExternalPrintServersAllowlist, + prefs::kExternalPrintServersAllowlist, base::Value::Type::LIST))); ++ handlers->AddHandler(std::make_unique( ++ key::kNearbyShareAllowed, prefs::kNearbySharingEnabledPrefName)); + #if defined(USE_CUPS) + handlers->AddHandler(std::make_unique( + key::kPrintingAPIExtensionsWhitelist, +diff -up chromium-86.0.4240.111/chrome/browser/prefs/browser_prefs.cc.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/prefs/browser_prefs.cc +--- chromium-86.0.4240.111/chrome/browser/prefs/browser_prefs.cc.disable-nearby_sharing 2020-10-22 10:31:22.225995479 -0400 ++++ chromium-86.0.4240.111/chrome/browser/prefs/browser_prefs.cc 2020-10-22 10:32:01.016348671 -0400 +@@ -760,7 +760,6 @@ void RegisterLocalState(PrefRegistrySimp + media_router::RegisterLocalStatePrefs(registry); + metrics::TabStatsTracker::RegisterPrefs(registry); + RegisterBrowserPrefs(registry); +- RegisterNearbySharingLocalPrefs(registry); + StartupBrowserCreator::RegisterLocalStatePrefs(registry); + task_manager::TaskManagerInterface::RegisterPrefs(registry); + UpgradeDetector::RegisterPrefs(registry); +@@ -836,6 +835,7 @@ void RegisterLocalState(PrefRegistrySimp + policy::SystemFeaturesDisableListPolicyHandler::RegisterPrefs(registry); + quirks::QuirksManager::RegisterPrefs(registry); + UpgradeDetectorChromeos::RegisterPrefs(registry); ++ RegisterNearbySharingLocalPrefs(registry); + #endif // defined(OS_CHROMEOS) + + #if defined(OS_MAC) +diff -up chromium-86.0.4240.111/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +--- chromium-86.0.4240.111/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc.disable-nearby_sharing 2020-10-22 10:32:20.862529372 -0400 ++++ chromium-86.0.4240.111/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc 2020-10-22 10:33:17.678046697 -0400 +@@ -44,7 +44,6 @@ + #include "chrome/browser/media/router/media_router_factory.h" + #include "chrome/browser/media/webrtc/webrtc_event_log_manager_keyed_service_factory.h" + #include "chrome/browser/media_galleries/media_galleries_preferences_factory.h" +-#include "chrome/browser/nearby_sharing/nearby_sharing_service_factory.h" + #include "chrome/browser/notifications/notifier_state_tracker_factory.h" + #include "chrome/browser/ntp_snippets/content_suggestions_service_factory.h" + #include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.h" +@@ -176,6 +175,7 @@ + + #if defined(OS_CHROMEOS) + #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler_user_service.h" ++#include "chrome/browser/nearby_sharing/nearby_sharing_service_factory.h" + #endif + + namespace chrome { +@@ -306,7 +306,7 @@ void ChromeBrowserMainExtraPartsProfiles + metrics::DesktopProfileSessionDurationsServiceFactory::GetInstance(); + #endif + ModelTypeStoreServiceFactory::GetInstance(); +-#if !defined(OS_ANDROID) ++#if defined(OS_CHROMEOS) + NearbySharingServiceFactory::GetInstance(); + #endif + NotifierStateTrackerFactory::GetInstance(); +diff -up chromium-86.0.4240.111/chrome/browser/resources/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/resources/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/resources/BUILD.gn.disable-nearby_sharing 2020-10-22 10:33:27.386135091 -0400 ++++ chromium-86.0.4240.111/chrome/browser/resources/BUILD.gn 2020-10-22 11:40:19.883762361 -0400 +@@ -38,7 +38,6 @@ if (enable_js_type_check) { + "management:closure_compile", + "media_router:closure_compile", + "nearby_internals:closure_compile", +- "nearby_share:closure_compile", + "nearby_share/shared:closure_compile", + "nearby_share/shared:closure_compile_module", + "new_tab_page:closure_compile", +@@ -60,7 +59,10 @@ if (enable_js_type_check) { + deps += [ "sandbox_internals:closure_compile" ] + } + if (is_chromeos) { +- deps += [ "chromeos:closure_compile" ] ++ deps += [ ++ "chromeos:closure_compile", ++ "nearby_share:closure_compile", ++ ] + } + if (enable_extensions) { + deps += [ "extensions:closure_compile" ] +@@ -208,50 +210,6 @@ if (!is_android) { + output_dir = "$root_gen_dir/chrome" + } + +- grit("nearby_internals_resources") { +- source = "nearby_internals/nearby_internals_resources.grd" +- +- grit_flags = [ +- "-E", +- "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), +- ] +- +- deps = [ "//chrome/browser/resources/nearby_internals:web_components" ] +- +- defines = chrome_grit_defines +- outputs = [ +- "grit/nearby_internals_resources.h", +- "grit/nearby_internals_resources_map.cc", +- "grit/nearby_internals_resources_map.h", +- "nearby_internals_resources.pak", +- ] +- output_dir = "$root_gen_dir/chrome" +- } +- +- grit("nearby_share_dialog_resources") { +- source = "nearby_share/nearby_share_dialog_resources.grd" +- +- grit_flags = [ +- "-E", +- "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), +- ] +- +- deps = [ +- "//chrome/browser/resources/nearby_share:web_components", +- "//chrome/browser/resources/nearby_share/shared:polymer3_elements", +- "//chrome/browser/ui/webui/nearby_share:mojom_js", +- ] +- +- defines = chrome_grit_defines +- outputs = [ +- "grit/nearby_share_dialog_resources.h", +- "grit/nearby_share_dialog_resources_map.cc", +- "grit/nearby_share_dialog_resources_map.h", +- "nearby_share_dialog_resources.pak", +- ] +- output_dir = "$root_gen_dir/chrome" +- } +- + grit("new_tab_page_resources") { + if (optimize_webui) { + source = "new_tab_page/new_tab_page_resources_vulcanized.grd" +@@ -360,6 +318,50 @@ if (is_chromeos) { + output_dir = "$root_gen_dir/chrome" + } + ++ grit("nearby_internals_resources") { ++ source = "nearby_internals/nearby_internals_resources.grd" ++ ++ grit_flags = [ ++ "-E", ++ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), ++ ] ++ ++ deps = [ "//chrome/browser/resources/nearby_internals:web_components" ] ++ ++ defines = chrome_grit_defines ++ outputs = [ ++ "grit/nearby_internals_resources.h", ++ "grit/nearby_internals_resources_map.cc", ++ "grit/nearby_internals_resources_map.h", ++ "nearby_internals_resources.pak", ++ ] ++ output_dir = "$root_gen_dir/chrome" ++ } ++ ++ grit("nearby_share_dialog_resources") { ++ source = "nearby_share/nearby_share_dialog_resources.grd" ++ ++ grit_flags = [ ++ "-E", ++ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), ++ ] ++ ++ deps = [ ++ "//chrome/browser/resources/nearby_share:web_components", ++ "//chrome/browser/resources/nearby_share/shared:polymer3_elements", ++ "//chrome/browser/ui/webui/nearby_share:mojom_js", ++ ] ++ ++ defines = chrome_grit_defines ++ outputs = [ ++ "grit/nearby_share_dialog_resources.h", ++ "grit/nearby_share_dialog_resources_map.cc", ++ "grit/nearby_share_dialog_resources_map.h", ++ "nearby_share_dialog_resources.pak", ++ ] ++ output_dir = "$root_gen_dir/chrome" ++ } ++ + grit("os_settings_resources") { + grit_flags = [ + "-E", +diff -up chromium-86.0.4240.111/chrome/browser/resources/nearby_share/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/resources/nearby_share/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/resources/nearby_share/BUILD.gn.disable-nearby_sharing 2020-10-22 10:37:40.598383248 -0400 ++++ chromium-86.0.4240.111/chrome/browser/resources/nearby_share/BUILD.gn 2020-10-22 10:37:57.036514858 -0400 +@@ -5,6 +5,8 @@ + import("//third_party/closure_compiler/compile_js.gni") + import("//tools/polymer/html_to_js.gni") + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + js_type_check("closure_compile") { + is_polymer3 = true + closure_flags = +diff -up chromium-86.0.4240.111/chrome/browser/ui/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/ui/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/ui/BUILD.gn.disable-nearby_sharing 2020-10-22 10:38:10.073619238 -0400 ++++ chromium-86.0.4240.111/chrome/browser/ui/BUILD.gn 2020-10-22 10:42:04.260496813 -0400 +@@ -372,7 +372,6 @@ static_library("ui") { + "//chrome/browser/image_decoder", + "//chrome/browser/media:mojo_bindings", + "//chrome/browser/media/feeds:mojo_bindings", +- "//chrome/browser/nearby_sharing/common", + "//chrome/browser/profiling_host", + "//chrome/browser/resources/invalidations:invalidations_resources", + "//chrome/browser/resources/media:webrtc_logs_resources", +@@ -1340,20 +1339,6 @@ static_library("ui") { + "webui/media_router/media_router_internals_webui_message_handler.cc", + "webui/media_router/media_router_internals_webui_message_handler.h", + "webui/media_router/web_contents_display_observer.h", +- "webui/nearby_internals/nearby_internals_contact_handler.cc", +- "webui/nearby_internals/nearby_internals_contact_handler.h", +- "webui/nearby_internals/nearby_internals_http_handler.cc", +- "webui/nearby_internals/nearby_internals_http_handler.h", +- "webui/nearby_internals/nearby_internals_logs_handler.cc", +- "webui/nearby_internals/nearby_internals_logs_handler.h", +- "webui/nearby_internals/nearby_internals_ui.cc", +- "webui/nearby_internals/nearby_internals_ui.h", +- "webui/nearby_internals/nearby_internals_ui_trigger_handler.cc", +- "webui/nearby_internals/nearby_internals_ui_trigger_handler.h", +- "webui/nearby_share/nearby_share_dialog_ui.cc", +- "webui/nearby_share/nearby_share_dialog_ui.h", +- "webui/nearby_share/shared_resources.cc", +- "webui/nearby_share/shared_resources.h", + "webui/new_tab_page/new_tab_page_handler.cc", + "webui/new_tab_page/new_tab_page_handler.h", + "webui/new_tab_page/new_tab_page_ui.cc", +@@ -1504,13 +1489,6 @@ static_library("ui") { + "//chrome/browser:theme_properties", + "//chrome/browser/media/kaleidoscope/mojom", + "//chrome/browser/media/router", +- "//chrome/browser/nearby_sharing/certificates", +- "//chrome/browser/nearby_sharing/client", +- "//chrome/browser/nearby_sharing/contacts", +- "//chrome/browser/nearby_sharing/local_device_data", +- "//chrome/browser/nearby_sharing/logging", +- "//chrome/browser/nearby_sharing/logging:util", +- "//chrome/browser/nearby_sharing/proto", + "//chrome/browser/profile_resetter:profile_reset_report_proto", + "//chrome/browser/promo_browser_command:mojo_bindings", + "//chrome/browser/resource_coordinator:tab_metrics_event_proto", +@@ -1520,8 +1498,6 @@ static_library("ui") { + "//chrome/browser/ui/color:mixers", + "//chrome/browser/ui/webui/app_management:mojo_bindings", + "//chrome/browser/ui/webui/internals/web_app:mojo_bindings", +- "//chrome/browser/ui/webui/nearby_share:mojom", +- "//chrome/browser/ui/webui/nearby_share/public/mojom", + "//chrome/common:buildflags", + "//chrome/common/media_router/mojom:media_router", + "//chrome/common/search:generate_chrome_colors_info", +@@ -2354,6 +2330,20 @@ static_library("ui") { + "webui/help/version_updater_chromeos.h", + "webui/management_ui_handler_chromeos.cc", + "webui/management_ui_handler_chromeos.h", ++ "webui/nearby_internals/nearby_internals_contact_handler.cc", ++ "webui/nearby_internals/nearby_internals_contact_handler.h", ++ "webui/nearby_internals/nearby_internals_http_handler.cc", ++ "webui/nearby_internals/nearby_internals_http_handler.h", ++ "webui/nearby_internals/nearby_internals_logs_handler.cc", ++ "webui/nearby_internals/nearby_internals_logs_handler.h", ++ "webui/nearby_internals/nearby_internals_ui.cc", ++ "webui/nearby_internals/nearby_internals_ui.h", ++ "webui/nearby_internals/nearby_internals_ui_trigger_handler.cc", ++ "webui/nearby_internals/nearby_internals_ui_trigger_handler.h", ++ "webui/nearby_share/nearby_share_dialog_ui.cc", ++ "webui/nearby_share/nearby_share_dialog_ui.h", ++ "webui/nearby_share/shared_resources.cc", ++ "webui/nearby_share/shared_resources.h", + "webui/settings/chromeos/about_section.cc", + "webui/settings/chromeos/about_section.h", + "webui/settings/chromeos/accessibility_handler.cc", +@@ -2500,6 +2490,14 @@ static_library("ui") { + "//chrome/browser/chromeos", + "//chrome/browser/chromeos:backdrop_wallpaper_proto", + "//chrome/browser/chromeos/crostini:crostini_installer_types_mojom", ++ "//chrome/browser/nearby_sharing/certificates", ++ "//chrome/browser/nearby_sharing/client", ++ "//chrome/browser/nearby_sharing/common", ++ "//chrome/browser/nearby_sharing/contacts", ++ "//chrome/browser/nearby_sharing/local_device_data", ++ "//chrome/browser/nearby_sharing/logging", ++ "//chrome/browser/nearby_sharing/logging:util", ++ "//chrome/browser/nearby_sharing/proto", + "//chrome/browser/resources:bluetooth_pairing_dialog_resources", + "//chrome/browser/ui/app_list/search/cros_action_history:cros_action_proto", + "//chrome/browser/ui/app_list/search/search_result_ranker:app_launch_event_logger_proto", +@@ -2513,6 +2511,8 @@ static_library("ui") { + "//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings", + "//chrome/browser/ui/webui/chromeos/file_manager:mojo_bindings", + "//chrome/browser/ui/webui/chromeos/machine_learning:mojo_bindings", ++ "//chrome/browser/ui/webui/nearby_share:mojom", ++ "//chrome/browser/ui/webui/nearby_share/public/mojom", + "//chrome/browser/ui/webui/settings/chromeos/constants:mojom", + "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings", + "//chrome/services/file_util/public/cpp", +diff -up chromium-86.0.4240.111/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +--- chromium-86.0.4240.111/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc.disable-nearby_sharing 2020-10-22 10:42:19.451627856 -0400 ++++ chromium-86.0.4240.111/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc 2020-10-22 10:45:12.011116391 -0400 +@@ -54,7 +54,6 @@ + #include "chrome/browser/ui/webui/media/media_history_ui.h" + #include "chrome/browser/ui/webui/media/webrtc_logs_ui.h" + #include "chrome/browser/ui/webui/memory_internals_ui.h" +-#include "chrome/browser/ui/webui/nearby_internals/nearby_internals_ui.h" + #include "chrome/browser/ui/webui/net_export_ui.h" + #include "chrome/browser/ui/webui/net_internals/net_internals_ui.h" + #include "chrome/browser/ui/webui/ntp_tiles_internals_ui.h" +@@ -138,7 +137,6 @@ + #include "chrome/browser/ui/webui/inspect_ui.h" + #include "chrome/browser/ui/webui/management_ui.h" + #include "chrome/browser/ui/webui/media_router/media_router_internals_ui.h" +-#include "chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h" + #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h" + #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" + #include "chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.h" +@@ -191,6 +189,8 @@ + #include "chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h" + #include "chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.h" + #include "chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_ui.h" ++#include "chrome/browser/ui/webui/nearby_internals/nearby_internals_ui.h" ++#include "chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h" + #include "chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h" + #include "chromeos/components/camera_app_ui/camera_app_ui.h" + #include "chromeos/components/camera_app_ui/url_constants.h" +@@ -540,14 +540,6 @@ WebUIFactoryFunction GetWebUIFactoryFunc + // Identity API is not available on Android. + if (url.host_piece() == chrome::kChromeUIIdentityInternalsHost) + return &NewWebUI; +- if (base::FeatureList::IsEnabled(features::kNearbySharing)) { +- if (url.host_piece() == chrome::kChromeUINearbyInternalsHost) +- return &NewWebUI; +- if (url.host_piece() == chrome::kChromeUINearbyShareHost && +- profile->IsRegularProfile()) { +- return &NewWebUI; +- } +- } + if (url.host_piece() == chrome::kChromeUINewTabHost) + return &NewWebUI; + if (url.host_piece() == chrome::kChromeUINewTabPageHost) +@@ -692,6 +684,15 @@ WebUIFactoryFunction GetWebUIFactoryFunc + return &NewWebUI; + } + ++ if (base::FeatureList::IsEnabled(features::kNearbySharing)) { ++ if (url.host_piece() == chrome::kChromeUINearbyInternalsHost) ++ return &NewWebUI; ++ if (url.host_piece() == chrome::kChromeUINearbyShareHost && ++ profile->IsRegularProfile()) { ++ return &NewWebUI; ++ } ++ } ++ + if (url.host_piece() == chrome::kChromeUIArcGraphicsTracingHost) + return &NewWebUI>; +diff -up chromium-86.0.4240.111/chrome/browser/ui/webui/nearby_share/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/browser/ui/webui/nearby_share/BUILD.gn +--- chromium-86.0.4240.111/chrome/browser/ui/webui/nearby_share/BUILD.gn.disable-nearby_sharing 2020-10-22 10:45:28.621259670 -0400 ++++ chromium-86.0.4240.111/chrome/browser/ui/webui/nearby_share/BUILD.gn 2020-10-22 10:45:42.070375681 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + import("//mojo/public/tools/bindings/mojom.gni") + + mojom("nearby_share_target_types") { +diff -up chromium-86.0.4240.111/chrome/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/BUILD.gn +--- chromium-86.0.4240.111/chrome/BUILD.gn.disable-nearby_sharing 2020-10-22 10:19:09.215710440 -0400 ++++ chromium-86.0.4240.111/chrome/BUILD.gn 2020-10-22 10:19:40.108955174 -0400 +@@ -1316,8 +1316,6 @@ group("extra_resources") { + "//chrome/browser/resources:gaia_auth_host_resources", + "//chrome/browser/resources:history_resources", + "//chrome/browser/resources:local_ntp_resources", +- "//chrome/browser/resources:nearby_internals_resources", +- "//chrome/browser/resources:nearby_share_dialog_resources", + "//chrome/browser/resources:new_tab_page_resources", + "//chrome/browser/resources:settings_resources", + ] +@@ -1327,6 +1325,8 @@ group("extra_resources") { + public_deps += [ + "//chrome/browser/resources:bluetooth_pairing_dialog_resources", + "//chrome/browser/resources:multidevice_internals_resources", ++ "//chrome/browser/resources:nearby_internals_resources", ++ "//chrome/browser/resources:nearby_share_dialog_resources", + "//chrome/browser/resources:os_settings_resources", + "//chrome/browser/resources/chromeos:cellular_setup_resources", + "//chrome/browser/resources/chromeos:multidevice_setup_resources", +diff -up chromium-86.0.4240.111/chrome/chrome_paks.gni.disable-nearby_sharing chromium-86.0.4240.111/chrome/chrome_paks.gni +--- chromium-86.0.4240.111/chrome/chrome_paks.gni.disable-nearby_sharing 2020-10-22 10:45:56.899503595 -0400 ++++ chromium-86.0.4240.111/chrome/chrome_paks.gni 2020-10-22 10:47:11.355145881 -0400 +@@ -136,8 +136,6 @@ template("chrome_extra_paks") { + "$root_gen_dir/chrome/gaia_auth_host_resources.pak", + "$root_gen_dir/chrome/history_resources.pak", + "$root_gen_dir/chrome/local_ntp_resources.pak", +- "$root_gen_dir/chrome/nearby_internals_resources.pak", +- "$root_gen_dir/chrome/nearby_share_dialog_resources.pak", + "$root_gen_dir/chrome/new_tab_page_resources.pak", + "$root_gen_dir/chrome/settings_resources.pak", + "$root_gen_dir/content/browser/devtools/devtools_resources.pak", +@@ -152,8 +150,6 @@ template("chrome_extra_paks") { + "//chrome/browser/resources:gaia_auth_host_resources", + "//chrome/browser/resources:history_resources", + "//chrome/browser/resources:local_ntp_resources", +- "//chrome/browser/resources:nearby_internals_resources", +- "//chrome/browser/resources:nearby_share_dialog_resources", + "//chrome/browser/resources:new_tab_page_resources", + "//chrome/browser/resources:settings_resources", + "//content/browser/devtools:devtools_resources", +@@ -168,6 +164,8 @@ template("chrome_extra_paks") { + "$root_gen_dir/chrome/cellular_setup_resources.pak", + "$root_gen_dir/chrome/multidevice_internals_resources.pak", + "$root_gen_dir/chrome/multidevice_setup_resources.pak", ++ "$root_gen_dir/chrome/nearby_internals_resources.pak", ++ "$root_gen_dir/chrome/nearby_share_dialog_resources.pak", + "$root_gen_dir/chrome/os_settings_resources.pak", + "$root_gen_dir/chromeos/chromeos_camera_app_resources.pak", + "$root_gen_dir/chromeos/chromeos_help_app_bundle_resources.pak", +@@ -184,6 +182,8 @@ template("chrome_extra_paks") { + "//ash/public/cpp/resources:ash_public_unscaled_resources", + "//chrome/browser/resources:bluetooth_pairing_dialog_resources", + "//chrome/browser/resources:multidevice_internals_resources", ++ "//chrome/browser/resources:nearby_internals_resources", ++ "//chrome/browser/resources:nearby_share_dialog_resources", + "//chrome/browser/resources:os_settings_resources", + "//chrome/browser/resources/chromeos:cellular_setup_resources", + "//chrome/browser/resources/chromeos:multidevice_setup_resources", +diff -up chromium-86.0.4240.111/chrome/services/sharing/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/services/sharing/BUILD.gn +--- chromium-86.0.4240.111/chrome/services/sharing/BUILD.gn.disable-nearby_sharing 2020-10-22 10:47:49.654476258 -0400 ++++ chromium-86.0.4240.111/chrome/services/sharing/BUILD.gn 2020-10-22 10:48:01.693580107 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + source_set("sharing") { + sources = [ + "sharing_impl.cc", +diff -up chromium-86.0.4240.111/chrome/services/sharing/nearby/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/services/sharing/nearby/BUILD.gn +--- chromium-86.0.4240.111/chrome/services/sharing/nearby/BUILD.gn.disable-nearby_sharing 2020-10-22 10:48:19.813736424 -0400 ++++ chromium-86.0.4240.111/chrome/services/sharing/nearby/BUILD.gn 2020-10-22 10:48:31.958841191 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + source_set("nearby") { + sources = [ + "nearby_connections.cc", +diff -up chromium-86.0.4240.111/chrome/test/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/test/BUILD.gn +--- chromium-86.0.4240.111/chrome/test/BUILD.gn.disable-nearby_sharing 2020-10-22 10:48:44.491949303 -0400 ++++ chromium-86.0.4240.111/chrome/test/BUILD.gn 2020-10-22 10:52:27.201870438 -0400 +@@ -3712,34 +3712,6 @@ test("unit_tests") { + "../browser/media/feeds/media_feeds_fetcher_unittest.cc", + "../browser/media/feeds/media_feeds_service_unittest.cc", + "../browser/media/kaleidoscope/kaleidoscope_switches_unittest.cc", +- "../browser/nearby_sharing/fake_nearby_connection.cc", +- "../browser/nearby_sharing/fake_nearby_connection.h", +- "../browser/nearby_sharing/fake_nearby_connections_manager.cc", +- "../browser/nearby_sharing/fake_nearby_connections_manager.h", +- "../browser/nearby_sharing/fast_initiation_manager_unittest.cc", +- "../browser/nearby_sharing/incoming_frames_reader_unittest.cc", +- "../browser/nearby_sharing/instantmessaging/fake_token_fetcher.cc", +- "../browser/nearby_sharing/instantmessaging/fake_token_fetcher.h", +- "../browser/nearby_sharing/instantmessaging/receive_messages_express_unittest.cc", +- "../browser/nearby_sharing/instantmessaging/send_message_express_unittest.cc", +- "../browser/nearby_sharing/instantmessaging/stream_parser_unittest.cc", +- "../browser/nearby_sharing/mock_nearby_connections.cc", +- "../browser/nearby_sharing/mock_nearby_connections.h", +- "../browser/nearby_sharing/mock_nearby_process_manager.cc", +- "../browser/nearby_sharing/mock_nearby_process_manager.h", +- "../browser/nearby_sharing/mock_nearby_sharing_decoder.cc", +- "../browser/nearby_sharing/mock_nearby_sharing_decoder.h", +- "../browser/nearby_sharing/mock_nearby_sharing_service.cc", +- "../browser/nearby_sharing/mock_nearby_sharing_service.h", +- "../browser/nearby_sharing/nearby_confirmation_manager_unittest.cc", +- "../browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc", +- "../browser/nearby_sharing/nearby_notification_manager_unittest.cc", +- "../browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc", +- "../browser/nearby_sharing/nearby_process_manager_unittest.cc", +- "../browser/nearby_sharing/nearby_share_settings_unittest.cc", +- "../browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc", +- "../browser/nearby_sharing/paired_key_verification_runner_unittest.cc", +- "../browser/nearby_sharing/webrtc_signaling_messenger_unittest.cc", + "../browser/password_manager/generated_password_leak_detection_pref_unittest.cc", + "../browser/performance_manager/test_support/page_discarding_utils.cc", + "../browser/performance_manager/test_support/page_discarding_utils.h", +@@ -4442,22 +4414,9 @@ test("unit_tests") { + } + + deps += [ +- "//chrome/browser/nearby_sharing/certificates:test_support", +- "//chrome/browser/nearby_sharing/certificates:unit_tests", +- "//chrome/browser/nearby_sharing/client:unit_tests", +- "//chrome/browser/nearby_sharing/contacts:test_support", +- "//chrome/browser/nearby_sharing/local_device_data:test_support", +- "//chrome/browser/nearby_sharing/local_device_data:unit_tests", +- "//chrome/browser/nearby_sharing/logging:unit_tests", +- "//chrome/browser/nearby_sharing/proto", +- "//chrome/browser/nearby_sharing/scheduling:unit_tests", + "//chrome/browser/promo_browser_command:mojo_bindings", + "//chrome/browser/resource_coordinator:tab_metrics_event_proto", + "//chrome/browser/resource_coordinator/tab_ranker:tab_features_test_helper", +- "//chrome/services/sharing:unit_tests", +- "//chrome/services/sharing/nearby:unit_tests", +- "//chrome/services/sharing/nearby/decoder:unit_tests", +- "//chrome/services/sharing/nearby/platform_v2:unit_tests", + "//chrome/services/sharing/public/cpp:unit_tests", + "//chrome/services/sharing/webrtc:unit_tests", + "//chrome/services/speech:unit_tests", +@@ -4618,6 +4577,34 @@ test("unit_tests") { + "../browser/metrics/perf/process_type_collector_unittest.cc", + "../browser/metrics/perf/profile_provider_chromeos_unittest.cc", + "../browser/metrics/perf/windowed_incognito_observer_unittest.cc", ++ "../browser/nearby_sharing/fake_nearby_connection.cc", ++ "../browser/nearby_sharing/fake_nearby_connection.h", ++ "../browser/nearby_sharing/fake_nearby_connections_manager.cc", ++ "../browser/nearby_sharing/fake_nearby_connections_manager.h", ++ "../browser/nearby_sharing/fast_initiation_manager_unittest.cc", ++ "../browser/nearby_sharing/incoming_frames_reader_unittest.cc", ++ "../browser/nearby_sharing/instantmessaging/fake_token_fetcher.cc", ++ "../browser/nearby_sharing/instantmessaging/fake_token_fetcher.h", ++ "../browser/nearby_sharing/instantmessaging/receive_messages_express_unittest.cc", ++ "../browser/nearby_sharing/instantmessaging/send_message_express_unittest.cc", ++ "../browser/nearby_sharing/instantmessaging/stream_parser_unittest.cc", ++ "../browser/nearby_sharing/mock_nearby_connections.cc", ++ "../browser/nearby_sharing/mock_nearby_connections.h", ++ "../browser/nearby_sharing/mock_nearby_process_manager.cc", ++ "../browser/nearby_sharing/mock_nearby_process_manager.h", ++ "../browser/nearby_sharing/mock_nearby_sharing_decoder.cc", ++ "../browser/nearby_sharing/mock_nearby_sharing_decoder.h", ++ "../browser/nearby_sharing/mock_nearby_sharing_service.cc", ++ "../browser/nearby_sharing/mock_nearby_sharing_service.h", ++ "../browser/nearby_sharing/nearby_confirmation_manager_unittest.cc", ++ "../browser/nearby_sharing/nearby_connections_manager_impl_unittest.cc", ++ "../browser/nearby_sharing/nearby_notification_manager_unittest.cc", ++ "../browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc", ++ "../browser/nearby_sharing/nearby_process_manager_unittest.cc", ++ "../browser/nearby_sharing/nearby_share_settings_unittest.cc", ++ "../browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc", ++ "../browser/nearby_sharing/paired_key_verification_runner_unittest.cc", ++ "../browser/nearby_sharing/webrtc_signaling_messenger_unittest.cc", + "../browser/notifications/chrome_ash_message_center_client_unittest.cc", + "../browser/notifications/web_page_notifier_controller_unittest.cc", + "../browser/policy/printing_restrictions_policy_handler_unittest.cc", +@@ -4714,10 +4701,23 @@ test("unit_tests") { + "//ash/resources/vector_icons", + "//ash/strings", + "//chrome/browser/chromeos:test_support", ++ "//chrome/browser/nearby_sharing/certificates:test_support", ++ "//chrome/browser/nearby_sharing/certificates:unit_tests", ++ "//chrome/browser/nearby_sharing/client:unit_tests", ++ "//chrome/browser/nearby_sharing/contacts:test_support", ++ "//chrome/browser/nearby_sharing/local_device_data:test_support", ++ "//chrome/browser/nearby_sharing/local_device_data:unit_tests", ++ "//chrome/browser/nearby_sharing/logging:unit_tests", ++ "//chrome/browser/nearby_sharing/proto", ++ "//chrome/browser/nearby_sharing/scheduling:unit_tests", + "//chrome/browser/resources/chromeos/zip_archiver/cpp:ziparchiver_unittests", + "//chrome/browser/ui/app_list/search/search_result_ranker:app_launch_predictor_proto", + "//chrome/browser/ui/app_list/search/search_result_ranker:recurrence_ranker_proto", + "//chrome/services/printing:pdf_thumbnailer_test", ++ "//chrome/services/sharing:unit_tests", ++ "//chrome/services/sharing/nearby:unit_tests", ++ "//chrome/services/sharing/nearby/decoder:unit_tests", ++ "//chrome/services/sharing/nearby/platform_v2:unit_tests", + "//chromeos/assistant:buildflags", + "//chromeos/services/machine_learning/public/cpp:test_support", + "//components/arc:arc_test_support", +diff -up chromium-86.0.4240.111/chrome/test/data/webui/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/test/data/webui/BUILD.gn +--- chromium-86.0.4240.111/chrome/test/data/webui/BUILD.gn.disable-nearby_sharing 2020-10-22 10:52:43.932014752 -0400 ++++ chromium-86.0.4240.111/chrome/test/data/webui/BUILD.gn 2020-10-22 10:53:57.654650679 -0400 +@@ -390,10 +390,13 @@ group("modulize") { + "./cr_components:modulize", + "./cr_components/chromeos:modulize", + "./cr_elements:modulize", +- "./nearby_share/shared:modulize", + "./resources:modulize", + "./settings:modulize", + ] ++ ++ if (is_chromeos) { ++ deps += [ "./nearby_share/shared:modulize" ] ++ } + } + + js_modulizer("modulize_local") { +@@ -415,8 +418,6 @@ group("closure_compile") { + ":closure_compile_local", + "cr_components:closure_compile", + "cr_elements:closure_compile", +- "nearby_share:closure_compile", +- "nearby_share/shared:closure_compile", + "print_preview:closure_compile", + "settings:closure_compile", + "signin:closure_compile", +@@ -428,6 +429,8 @@ group("closure_compile") { + deps += [ + "chromeos/account_manager:closure_compile", + "chromeos/gaia_action_buttons:closure_compile", ++ "nearby_share:closure_compile", ++ "nearby_share/shared:closure_compile", + ] + } + if (enable_tab_search) { +diff -up chromium-86.0.4240.111/chrome/test/data/webui/nearby_share/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/test/data/webui/nearby_share/BUILD.gn +--- chromium-86.0.4240.111/chrome/test/data/webui/nearby_share/BUILD.gn.disable-nearby_sharing 2020-10-22 10:54:34.775970912 -0400 ++++ chromium-86.0.4240.111/chrome/test/data/webui/nearby_share/BUILD.gn 2020-10-22 10:54:46.864075184 -0400 +@@ -2,6 +2,8 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + import("//third_party/closure_compiler/compile_js.gni") + + js_type_check("closure_compile") { +diff -up chromium-86.0.4240.111/chrome/test/data/webui/nearby_share/shared/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/test/data/webui/nearby_share/shared/BUILD.gn +--- chromium-86.0.4240.111/chrome/test/data/webui/nearby_share/shared/BUILD.gn.disable-nearby_sharing 2020-10-22 10:54:59.769186503 -0400 ++++ chromium-86.0.4240.111/chrome/test/data/webui/nearby_share/shared/BUILD.gn 2020-10-22 10:55:19.761358952 -0400 +@@ -6,6 +6,8 @@ import("//third_party/closure_compiler/c + import("//ui/webui/resources/tools/js_modulizer.gni") + import("../../namespace_rewrites.gni") + ++assert(is_chromeos, "Nearby Share is CrOS only") ++ + js_modulizer("modulize") { + input_files = [ + "fake_nearby_share_settings.js", +diff -up chromium-86.0.4240.111/chrome/utility/BUILD.gn.disable-nearby_sharing chromium-86.0.4240.111/chrome/utility/BUILD.gn +--- chromium-86.0.4240.111/chrome/utility/BUILD.gn.disable-nearby_sharing 2020-10-22 10:55:36.484503205 -0400 ++++ chromium-86.0.4240.111/chrome/utility/BUILD.gn 2020-10-22 10:56:33.962999047 -0400 +@@ -105,8 +105,6 @@ static_library("utility") { + deps += [ + "//chrome/common:mojo_bindings", + "//chrome/common/importer:interfaces", +- "//chrome/services/sharing", +- "//chrome/services/sharing/public/mojom", + "//chrome/services/speech:lib", + "//components/autofill/core/common", + "//services/proxy_resolver:lib", +@@ -158,6 +156,8 @@ static_library("utility") { + if (is_chromeos) { + deps += [ + "//chrome/services/file_util", ++ "//chrome/services/sharing", ++ "//chrome/services/sharing/public/mojom:mojom", + "//chromeos/assistant:buildflags", + "//chromeos/services/ime:lib", + "//chromeos/services/ime/public/mojom", +diff -up chromium-86.0.4240.111/chrome/utility/services.cc.disable-nearby_sharing chromium-86.0.4240.111/chrome/utility/services.cc +--- chromium-86.0.4240.111/chrome/utility/services.cc.disable-nearby_sharing 2020-10-22 10:57:41.428581007 -0400 ++++ chromium-86.0.4240.111/chrome/utility/services.cc 2020-10-22 10:59:20.073427761 -0400 +@@ -40,8 +40,6 @@ + + #if !defined(OS_ANDROID) + #include "chrome/common/importer/profile_import.mojom.h" +-#include "chrome/services/sharing/public/mojom/sharing.mojom.h" +-#include "chrome/services/sharing/sharing_impl.h" + #include "chrome/services/speech/speech_recognition_service_impl.h" + #include "chrome/utility/importer/profile_import_impl.h" + #include "components/mirroring/service/mirroring_service.h" +@@ -84,6 +82,8 @@ + #include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h" + + #if defined(OS_CHROMEOS) ++#include "chrome/services/sharing/public/mojom/sharing.mojom.h" // nogncheck ++#include "chrome/services/sharing/sharing_impl.h" + #include "chromeos/assistant/buildflags.h" // nogncheck + #include "chromeos/services/ime/ime_service.h" + #include "chromeos/services/ime/public/mojom/input_engine.mojom.h" +@@ -162,10 +162,6 @@ auto RunMirroringService( + std::move(receiver), content::UtilityThread::Get()->GetIOTaskRunner()); + } + +-auto RunSharing(mojo::PendingReceiver receiver) { +- return std::make_unique(std::move(receiver)); +-} +- + auto RunSpeechRecognitionService( + mojo::PendingReceiver receiver) { + return std::make_unique( +@@ -234,6 +230,10 @@ auto RunImeService( + return std::make_unique(std::move(receiver)); + } + ++auto RunSharing(mojo::PendingReceiver receiver) { ++ return std::make_unique(std::move(receiver)); ++} ++ + auto RunTtsService( + mojo::PendingReceiver receiver) { + return std::make_unique(std::move(receiver)); +@@ -277,7 +277,6 @@ mojo::ServiceFactory* GetMainThreadServi + #if !defined(OS_ANDROID) + RunProfileImporter, + RunMirroringService, +- RunSharing, + RunSpeechRecognitionService, + #endif + +@@ -319,6 +318,7 @@ mojo::ServiceFactory* GetMainThreadServi + + #if defined(OS_CHROMEOS) + RunImeService, ++ RunSharing, + RunTtsService, + #if BUILDFLAG(ENABLE_CROS_LIBASSISTANT) + RunAssistantAudioDecoder, +--- chromium-86.0.4240.111/chrome/browser/chrome_browser_interface_binders.cc.disable-nearby_sharing 2020-10-23 11:27:09.341639045 -0400 ++++ chromium-86.0.4240.111/chrome/browser/chrome_browser_interface_binders.cc 2020-10-23 11:33:52.598575049 -0400 +@@ -117,9 +117,6 @@ + #include "chrome/browser/ui/webui/downloads/downloads.mojom.h" + #include "chrome/browser/ui/webui/downloads/downloads_ui.h" + #include "chrome/browser/ui/webui/media/media_feeds_ui.h" +-#include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h" +-#include "chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h" +-#include "chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom.h" + #include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h" + #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h" + #include "chrome/browser/ui/webui/read_later/read_later.mojom.h" +@@ -162,6 +159,9 @@ + #include "chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h" + #include "chrome/browser/ui/webui/chromeos/network_ui.h" + #include "chrome/browser/ui/webui/internals/web_app/web_app_internals.mojom.h" ++#include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h" ++#include "chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h" ++#include "chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom.h" + #include "chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h" + #include "chrome/browser/ui/webui/settings/chromeos/search/search.mojom.h" + #include "chrome/browser/ui/webui/settings/chromeos/search/user_action_recorder.mojom.h" +@@ -525,12 +525,6 @@ + RegisterWebUIControllerInterfaceBinder(map); + +- if (base::FeatureList::IsEnabled(features::kNearbySharing)) { +- RegisterWebUIControllerInterfaceBinder< +- nearby_share::mojom::DiscoveryManager, +- nearby_share::NearbyShareDialogUI>(map); +- } +- + RegisterWebUIControllerInterfaceBinder< + new_tab_page::mojom::PageHandlerFactory, NewTabPageUI>(map); + +@@ -673,16 +667,13 @@ + nearby_share::mojom::NearbyShareSettings, + chromeos::settings::OSSettingsUI, nearby_share::NearbyShareDialogUI>( + map); ++ RegisterWebUIControllerInterfaceBinder< ++ nearby_share::mojom::DiscoveryManager, ++ nearby_share::NearbyShareDialogUI>(map); + } + #endif // defined(OS_CHROMEOS) + + #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) +- if (base::FeatureList::IsEnabled(features::kNearbySharing)) { +- RegisterWebUIControllerInterfaceBinder< +- nearby_share::mojom::NearbyShareSettings, +- nearby_share::NearbyShareDialogUI>(map); +- } +- + if (base::FeatureList::IsEnabled(features::kNewProfilePicker)) { + RegisterWebUIControllerInterfaceBinder< + customize_themes::mojom::CustomizeThemesHandlerFactory, diff --git a/chromium.spec b/chromium.spec index abedb50b..e3fe49e6 100644 --- a/chromium.spec +++ b/chromium.spec @@ -275,10 +275,6 @@ Patch70: chromium-84.0.4147.125-i686-fix_textrels.patch Patch71: chromium-84.0.4147.125-aarch64-clearkeycdm-binutils-workaround.patch # https://github.com/chromium/chromium/commit/53478caee862624fc6d73516f8d64253854b146f Patch72: chromium-85.0.4183.102-invalid-end-CookieMonster-53478ca.patch -# EL7 failed to compile without this, but it seems accurate for all branches -# just a bit taken from -# https://github.com/chromium/chromium/commit/a61fb57edb75fcfe251af0e6f66820d13924ad62 -Patch73: chromium-86-use-range-based-algorithms.patch # Use lstdc++ on EPEL7 only Patch101: chromium-75.0.3770.100-epel7-stdc++.patch @@ -298,6 +294,10 @@ Patch107: chromium-84.0.4147.89-el8-arm-incompatible-ints.patch # libdrm on EL7 is rather old and chromium assumes newer # This gets us by for now Patch108: chromium-85.0.4183.83-el7-old-libdrm.patch +# Move nearby_share code to chromeos only on EL7 +# Why? Because something in it fails to build on EL7 (and only there) +# And upstream later sets it to chromeos only anyway +Patch109: chromium-86.0.4240.111-el7-limit-nearby-sharing-to-chromeos.patch # VAAPI # Upstream turned VAAPI on in Linux in 86 @@ -896,7 +896,6 @@ udev. %patch70 -p1 -b .i686-textrels %patch71 -p1 -b .aarch64-clearkeycdm-binutils-workaround %patch72 -p1 -b .invalid-end-CookieMonster -%patch73 -p1 -b .a61fb57e # Fedora branded user agent %if 0%{?fedora} @@ -910,6 +909,7 @@ udev. %patch103 -p1 -b .epel7-kcmp %patch104 -p1 -b .el7cups %patch108 -p1 -b .el7-old-libdrm +%patch109 -p1 -b .disable-nearby_sharing %endif %if 0%{?rhel} == 8