Как правильно использовать std::begin и std::end?

1,00
р.
Начиная с С++11, в стандарт были добавлены функции std::begin и std::end, которые можно использовать вместо методов .begin() и .end().
Как и когда их надо использовать?

Ответ
Наиболее известное свойство функций std::begin и std::end - это то, что они работают с массивами:
int a[3] = {1, 2, 3} int sum = std::accumulate(std::begin(a), std::end(a), 0)
Для контейнеров-классов, если тип контейнера известен, единственное преимущество свободной функции std::begin() перед функцией-членом - это то, что код получается на один символ короче:
std::vector v = {1, 2, 3} std::reverse(begin(v), end(v)) std::reverse(v.begin(), v.end())
Здесь префикс std:: указывать не надо, т.к. работает поиск имен, зависящих от аргументов (ADL): vector находится в пространстве имен std, по этому для него будет найдена функция std::begin (из того же пространства имен).

В обобщенном коде надо использовать using std::begin
Так как существует поиск имен (ADL), то нужные функции begin и end могут находиться в другом пространстве имен (не std). Однако с массивами работают только функции из std, по этому в шаблонных функциях надо явно добавлять std::begin и std::end в область видимости:
template int sum(Container& c) { using std::begin // Поиск имен также будет искать std::begin. using std::end return std::accumulate(begin(c), end(c), 0) }
Если сюда передать контейнер-класс, который находится в каком-либо пространстве имен, то будут использованы функции begin() и end() из этого пространства имен. Если же таких функций нет, или Container - это обычный массив, то будут вызваны функции std::begin и std::end. Для контейнеров-классов будут вызваны методы .begin() и .end().
Это можно продемонстрировать следующим примером (Код полностью)
struct GlobalArray { ... int* begin() { return arr } int* end() { return arr + N } }
namespace ns { struct Array {...} int* begin(Array& a) int* end(Array& a) }
int main() { ns::Array ns_arr for (auto& x : ns_arr) x = 1 // В sum() будут использованы ns::begin и ns::end std::cout << sum(ns_arr) << '<br>'
std::vector v = {1, 20, 300} // Будут использованы std::begin и std::end, которые вызовут методы .begin() и .end() std::cout << sum(v) << '<br>'
int c_arr[] = {400, 50, 6} // Будут использованы std::begin и std::end std::cout << sum(c_arr) << '<br>'
GlobalArray glob_arr for (auto& x : glob_arr) x = 1 // Будут использованы std::begin и std::end, которые вызовут методы .begin() и .end() std::cout << sum(glob_arr) << '<br>' }