1*6777b538SAndroid Build Coastguard Worker# `base::ranges` 2*6777b538SAndroid Build Coastguard Worker 3*6777b538SAndroid Build Coastguard WorkerThis directory aims to implement a C++14 version of the new `std::ranges` 4*6777b538SAndroid Build Coastguard Workeralgorithms that were introduced in C++20. These implementations are added to the 5*6777b538SAndroid Build Coastguard Worker`::base::ranges` namespace, and callers can access them by including 6*6777b538SAndroid Build Coastguard Worker[`base/ranges/algorithm.h`](https://source.chromium.org/chromium/chromium/src/+/main:base/ranges/algorithm.h). 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker## Similarities with C++20: 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker### Automatically deducing `begin()` and `end()` 11*6777b538SAndroid Build Coastguard WorkerAs probably one of the most important changes for readability and usability, all 12*6777b538SAndroid Build Coastguard Workeralgorithms in `base::ranges` have overloads for ranges of elements, which allow 13*6777b538SAndroid Build Coastguard Workercallers to no longer specify `begin()` and `end()` iterators themselves. 14*6777b538SAndroid Build Coastguard Worker 15*6777b538SAndroid Build Coastguard WorkerBefore: 16*6777b538SAndroid Build Coastguard Worker```c++ 17*6777b538SAndroid Build Coastguard Workerbool HasEvens(const std::vector<int>& vec) { 18*6777b538SAndroid Build Coastguard Worker return std::any_of(vec.begin(), vec.end(), [](int i) { return i % 2 == 0; }); 19*6777b538SAndroid Build Coastguard Worker} 20*6777b538SAndroid Build Coastguard Worker``` 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard WorkerAfter: 23*6777b538SAndroid Build Coastguard Worker```c++ 24*6777b538SAndroid Build Coastguard Workerbool HasEvens(const std::vector<int>& vec) { 25*6777b538SAndroid Build Coastguard Worker return base::ranges::any_of(vec, [](int i) { return i % 2 == 0; }); 26*6777b538SAndroid Build Coastguard Worker} 27*6777b538SAndroid Build Coastguard Worker``` 28*6777b538SAndroid Build Coastguard Worker 29*6777b538SAndroid Build Coastguard WorkerFurthermore, these overloads also support binding to temporaries, so that 30*6777b538SAndroid Build Coastguard Workerapplying algorithms to return values is easier: 31*6777b538SAndroid Build Coastguard Worker 32*6777b538SAndroid Build Coastguard Worker```c++ 33*6777b538SAndroid Build Coastguard Workerstd::vector<int> GetNums(); 34*6777b538SAndroid Build Coastguard Worker``` 35*6777b538SAndroid Build Coastguard Worker 36*6777b538SAndroid Build Coastguard WorkerBefore: 37*6777b538SAndroid Build Coastguard Worker 38*6777b538SAndroid Build Coastguard Worker```c++ 39*6777b538SAndroid Build Coastguard Workerbool HasEvens() { 40*6777b538SAndroid Build Coastguard Worker std::vector<int> nums = GetNums(); 41*6777b538SAndroid Build Coastguard Worker return std::any_of(nums.begin(), nums.end(), 42*6777b538SAndroid Build Coastguard Worker [](int i) { return i % 2 == 0; }); 43*6777b538SAndroid Build Coastguard Worker} 44*6777b538SAndroid Build Coastguard Worker``` 45*6777b538SAndroid Build Coastguard Worker 46*6777b538SAndroid Build Coastguard WorkerAfter: 47*6777b538SAndroid Build Coastguard Worker```c++ 48*6777b538SAndroid Build Coastguard Workerbool HasEvens() { 49*6777b538SAndroid Build Coastguard Worker return base::ranges::any_of(GetNums(), [](int i) { return i % 2 == 0; }); 50*6777b538SAndroid Build Coastguard Worker} 51*6777b538SAndroid Build Coastguard Worker``` 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Worker### Support for Projections 54*6777b538SAndroid Build Coastguard WorkerIn addition to supporting automatically deducing the `begin()` and `end()` 55*6777b538SAndroid Build Coastguard Workeriterator for ranges, the `base::ranges::` algorithms also support projections, 56*6777b538SAndroid Build Coastguard Workerthat can be applied to arguments prior to passing it to supplied transformations 57*6777b538SAndroid Build Coastguard Workeror predicates. This is especially useful when ordering a collection of classes 58*6777b538SAndroid Build Coastguard Workerby a specific data member of the class. Example: 59*6777b538SAndroid Build Coastguard Worker 60*6777b538SAndroid Build Coastguard WorkerBefore: 61*6777b538SAndroid Build Coastguard Worker```cpp 62*6777b538SAndroid Build Coastguard Workerstd::sort(suggestions->begin(), suggestions->end(), 63*6777b538SAndroid Build Coastguard Worker [](const autofill::Suggestion& a, const autofill::Suggestion& b) { 64*6777b538SAndroid Build Coastguard Worker return a.match < b.match; 65*6777b538SAndroid Build Coastguard Worker }); 66*6777b538SAndroid Build Coastguard Worker``` 67*6777b538SAndroid Build Coastguard Worker 68*6777b538SAndroid Build Coastguard WorkerAfter: 69*6777b538SAndroid Build Coastguard Worker```cpp 70*6777b538SAndroid Build Coastguard Workerbase::ranges::sort(*suggestions, /*comp=*/{}, &autofill::Suggestion::match); 71*6777b538SAndroid Build Coastguard Worker``` 72*6777b538SAndroid Build Coastguard Worker 73*6777b538SAndroid Build Coastguard WorkerAnything that is callable can be used as a projection. This includes 74*6777b538SAndroid Build Coastguard Worker`FunctionObjects` like function pointers or functors, but also pointers to 75*6777b538SAndroid Build Coastguard Workermember function and pointers to data members, as shown above. When not specified 76*6777b538SAndroid Build Coastguard Workera projection defaults to `base::ranges::identity`, which simply perfectly 77*6777b538SAndroid Build Coastguard Workerforwards its argument. 78*6777b538SAndroid Build Coastguard Worker 79*6777b538SAndroid Build Coastguard WorkerProjections are supported in both range and iterator-pair overloads of the 80*6777b538SAndroid Build Coastguard Worker`base::ranges::` algorithms, for example `base::ranges::all_of` has the 81*6777b538SAndroid Build Coastguard Workerfollowing signatures: 82*6777b538SAndroid Build Coastguard Worker 83*6777b538SAndroid Build Coastguard Worker```cpp 84*6777b538SAndroid Build Coastguard Workertemplate <typename InputIterator, typename Pred, typename Proj = identity> 85*6777b538SAndroid Build Coastguard Workerbool all_of(InputIterator first, InputIterator last, Pred pred, Proj proj = {}); 86*6777b538SAndroid Build Coastguard Worker 87*6777b538SAndroid Build Coastguard Workertemplate <typename Range, typename Pred, typename Proj = identity> 88*6777b538SAndroid Build Coastguard Workerbool all_of(Range&& range, Pred pred, Proj proj = {}); 89*6777b538SAndroid Build Coastguard Worker``` 90*6777b538SAndroid Build Coastguard Worker 91*6777b538SAndroid Build Coastguard Worker## Differences from C++20: 92*6777b538SAndroid Build Coastguard WorkerTo simplify the implementation of the `base::ranges::` algorithms, they dispatch 93*6777b538SAndroid Build Coastguard Workerto the `std::` algorithms found in C++14. This leads to the following list of 94*6777b538SAndroid Build Coastguard Workerdifferences from C++20. Since most of these differences are differences in the 95*6777b538SAndroid Build Coastguard Workerlibrary and not in the language, they could be addressed in the future by adding 96*6777b538SAndroid Build Coastguard Workercorresponding implementations. 97*6777b538SAndroid Build Coastguard Worker 98*6777b538SAndroid Build Coastguard Worker### Lack of Constraints 99*6777b538SAndroid Build Coastguard WorkerDue to the lack of support for concepts in the language, the algorithms in 100*6777b538SAndroid Build Coastguard Worker`base::ranges` do not have the constraints that are present on the algorithms in 101*6777b538SAndroid Build Coastguard Worker`std::ranges`. Instead, they support any type, much like C++14's `std::` 102*6777b538SAndroid Build Coastguard Workeralgorithms. In the future this might be addressed by adding corresponding 103*6777b538SAndroid Build Coastguard Workerconstraints via SFINAE, should the need arise. 104*6777b538SAndroid Build Coastguard Worker 105*6777b538SAndroid Build Coastguard Worker### Lack of Range Primitives 106*6777b538SAndroid Build Coastguard WorkerDue to C++14's lack of `std::ranges` concepts like sentinels and other range 107*6777b538SAndroid Build Coastguard Workerprimitives, algorithms taking a `[first, last)` pair rather than a complete 108*6777b538SAndroid Build Coastguard Workerrange, do not support different types for `first` and `last`. Since they rely on 109*6777b538SAndroid Build Coastguard WorkerC++14's implementation, the type must be the same. This could be addressed in 110*6777b538SAndroid Build Coastguard Workerthe future by implementing support for sentinel types ourselves. 111*6777b538SAndroid Build Coastguard Worker 112*6777b538SAndroid Build Coastguard Worker### Lack of `constexpr` 113*6777b538SAndroid Build Coastguard WorkerThe `base::ranges` algorithms can only be used in a `constexpr` context when 114*6777b538SAndroid Build Coastguard Workerthey call underlying `std::` algorithms that are themselves `constexpr`. Before 115*6777b538SAndroid Build Coastguard WorkerC++20, only `std::min`, `std::max` and `std::minmax` are annotated 116*6777b538SAndroid Build Coastguard Workerappropriately, so code like `constexpr bool foo = base::ranges::any_of(...);` 117*6777b538SAndroid Build Coastguard Workerwill fail because the compiler will not find a `constexpr std::any_of`. This 118*6777b538SAndroid Build Coastguard Workercould be addressed by either upgrading Chromium's STL to C++20, or implementing 119*6777b538SAndroid Build Coastguard Worker`constexpr` versions of some of these algorithms ourselves. 120*6777b538SAndroid Build Coastguard Worker 121*6777b538SAndroid Build Coastguard Worker### Lack of post C++14 algorithms 122*6777b538SAndroid Build Coastguard WorkerSince most algorithms in `base::ranges` dispatch to their C++14 equivalent, some 123*6777b538SAndroid Build Coastguard Worker`std::` algorithms that are not present in C++14 have no implementation in 124*6777b538SAndroid Build Coastguard Worker`base::ranges`. This list of algorithms includes the following: 125*6777b538SAndroid Build Coastguard Worker 126*6777b538SAndroid Build Coastguard Worker- [`std::sample`](https://en.cppreference.com/w/cpp/algorithm/sample) (added in C++17) 127*6777b538SAndroid Build Coastguard Worker 128*6777b538SAndroid Build Coastguard Worker### Return Types 129*6777b538SAndroid Build Coastguard WorkerSome of the algorithms in `std::ranges::` have different return types than their 130*6777b538SAndroid Build Coastguard Workerequivalent in `std::`. For example, while `std::for_each` returns the passed-in 131*6777b538SAndroid Build Coastguard Worker`Function`, `std::ranges::for_each` returns a `std::ranges::for_each_result`, 132*6777b538SAndroid Build Coastguard Workerconsisting of the `last` iterator and the function. 133*6777b538SAndroid Build Coastguard Worker 134*6777b538SAndroid Build Coastguard WorkerIn the cases where the return type differs, `base::ranges::` algorithms will 135*6777b538SAndroid Build Coastguard Workercontinue to return the old return type. 136*6777b538SAndroid Build Coastguard Worker 137*6777b538SAndroid Build Coastguard Worker### No blocking of ADL 138*6777b538SAndroid Build Coastguard WorkerThe algorithms defined in `std::ranges` are not found by ADL, and inhibit ADL 139*6777b538SAndroid Build Coastguard Workerwhen found by [unqualified name lookup][1]. This is done to be able to enforce 140*6777b538SAndroid Build Coastguard Workerthe constraints specified by those algorithms and commonly implemented by using 141*6777b538SAndroid Build Coastguard Workerfunction objects instead of regular functions. Since we don't support 142*6777b538SAndroid Build Coastguard Workerconstrained algorithms yet, we don't implement the blocking of ADL either. 143*6777b538SAndroid Build Coastguard Worker 144*6777b538SAndroid Build Coastguard Worker[1]: https://wg21.link/algorithms.requirements#2 145