add tag
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!

This room is for discussion about this question.

Once logged in you can direct comments to any contributor here.

Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.