Introduce std::distance and std::advance in algorithm notebooks
Compare changes
<div class="toc"><ul class="toc-item"><li><span><a href="#Introduction" data-toc-modified-id="Introduction-1">Introduction</a></span></li><li><span><a href="#Example:-std::sort" data-toc-modified-id="Example:-std::sort-2">Example: <code>std::sort</code></a></span></li><li><span><a href="#std::find" data-toc-modified-id="std::find-3"><code>std::find</code></a></span></li><li><span><a href="#Output-iterators-and-std::back_inserter" data-toc-modified-id="Output-iterators-and-std::back_inserter-4">Output iterators and <code>std::back_inserter</code></a></span></li><li><span><a href="#The-different-kinds-of-operators" data-toc-modified-id="The-different-kinds-of-operators-5">The different kinds of operators</a></span></li><li><span><a href="#Algorithm:-read-the-documentation-first!" data-toc-modified-id="Algorithm:-read-the-documentation-first!-6">Algorithm: read the documentation first!</a></span><ul class="toc-item"><li><span><a href="#std::unique" data-toc-modified-id="std::unique-6.1">std::unique</a></span></li><li><span><a href="#std::remove_if" data-toc-modified-id="std::remove_if-6.2">std::remove_if</a></span></li></ul></li><li><span><a href="#Conclusion" data-toc-modified-id="Conclusion-7">Conclusion</a></span></li></ul></div>
Even if C++ can't be qualified as a _batteries included_ language like Python (until C++ 17 there was no proper filesystem management, and the support of this feature was still shaky at best in several STL implementations circa 2019...), there are plenty of algorithms that are already provided within the STL.
We won't obviously list them all here - the mighty \cite{Josuttis2012} which is more than 1000 pages long don't do it either! - but show few examples on how to use them. For instance, many STL algorithms rely upon iterators: this way a same algorithm may be used as well on `std::vector`, `std::list`, and so on...
```
```
```
```
```
```
```
```
The issue is that the memory is not allocated first: the algorithm doesn't provide the memory at destination! (the reason is that an algorithm is as generic as possible; here `std::copy_if` is expected to work as well with `std::set`... and `std::vector` and `std::set` don't use the same API to allocate the memory).
Of course, in some cases it is tricky to know in advance what you need, and here computing it previously with `std::count_if` adds an additional operation. There is actually a way to tell the program to insert the values by `push_back` with `std::back_inserter`; it might be a good idea to reserve enough memory to use this method without recopy:
```
```
```
```
```
```
However, it is a compelling argument to use algorithms instead of hand-made loops and functions: it should provide an easy way to optimize your code (even if as noted [on Cppreference](https://en.cppreference.com/w/cpp/algorithm/execution_policy_tag_t) you need to take usual precautions against data races).
You need however to be very careful: sometimes the names are unfortunately misleading, and you should always check a function does the job you have in mind. Algorithms were written to be as generic as possible, and can't do some operations such as allocate or deallocate memory as it would break this genericity.
I have barely scratched the surface; many algorithms are extremely useful. So whenever you want to proceed with a transformation that is likely common (check a range is sorted, partition a list in a specific way, finding minimum and maximum, etc...) it is highly likely the STL has something in store for you.
It is also important to highlight that while the STL algorithms may provide you efficiency (this library is written by highly skilled engineers after all), this is not its main draw: the algorithms are written to be as generic as possible. The primary reason to use them is to allow you to think at a higher level of abstraction, not to get the fastest possible implementation. So if your ~~intuition~~ benchmarking has shown that the standard library is causing a critical slowdown, you are free to explore classic alternatives such as [loop unrolling](https://en.wikipedia.org/wiki/Loop_unrolling) - that's one of the strength of the language (and the STL itself opens up this possibility directly for some of its construct - you may for instance use your own memory allocator when defining a container). For most purposes however that will not be necessary.
FYI, C++ 20 introduces a completely new way to deal with algorithms, which does not rely on direct use of iterators but instead on a range library. This leads to a syntax which is more akin to what is done in other languages - see for instance this example [@Coliru](https://coliru.stacked-crooked.com/a/efbfb359b4dfa6ee):
```