Jonathan Mee
Containers have methods which provide range access. Why does modern C++ provide redundant [non-member functions for range access](https://en.cppreference.com/w/cpp/iterator#Range_access) to the same containers?
C++11 provided:
* [`std::begin`](https://en.cppreference.com/w/cpp/iterator/begin)
* [`std::end`](https://en.cppreference.com/w/cpp/iterator/end)
C++14 provided:
* [`std::cbegin`](https://en.cppreference.com/w/cpp/iterator/begin)
* [`std::cend`](https://en.cppreference.com/w/cpp/iterator/end)
* [`std::crbegin`](https://en.cppreference.com/w/cpp/iterator/rbegin)
* [`std::crend`](https://en.cppreference.com/w/cpp/iterator/rend)
* [`std::rbegin`](https://en.cppreference.com/w/cpp/iterator/rbegin)
* [`std::rend`](https://en.cppreference.com/w/cpp/iterator/rend)
C++17 provided:
* [`std::data`](https://en.cppreference.com/w/cpp/iterator/data)
* [`std::empty`](https://en.cppreference.com/w/cpp/iterator/empty)
* [`std::size`](https://en.cppreference.com/w/cpp/iterator/size)
C++20 provided:
* [`std::ssize`](https://en.cppreference.com/w/cpp/iterator/size)
Top Answer
Jonathan Mee
The [stated motivation](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4017.htm) for the inclusion of these functions in the standard was to:
> Provide benefits in regards to safety, efficiency, and generality
Herb Sutter elaborates on this in the "Nonmember begin and end" section of his [Elements of Modern C++ Style](https://herbsutter.com/elements-of-modern-c-style/):
> Always use nonmember `begin(x)` and `end(x)` (not `x.begin()` and `x.end()`), because `begin(x)` and `end(x)` are extensible and can be adapted to work with all container types – even arrays – not just containers that follow the STL style of providing `x.begin()` and `x.end()` member functions
Today beyond containers and arrays these range access functions also apply to `std::initializer_lists`s and ranges. In addition Herb Sutter points out that even non-STL containers types, which do not provide `begin` and `end` methods, can be retrofitted with non-member `std::begin` and `std::end` functions so, "You can traverse collections of that type using the same coding style above as for STL containers."
---
Ultimately, the purpose of non-member functions for range access is to generalizes the code such that no change is necessary were the accessed container to be changed from a `std::vector` to an array or even a range.
With both [C++20's constraints and concepts](https://en.cppreference.com/w/cpp/language/constraints) and non-member functions for range access, the advent of [container based algorithms](https://herbsutter.com/2011/10/07/why-no-container-based-algorithms/) may be upon us!