Используйте `span<T>` или `span_p<T>` для обозначения полуоткрытой последовательности
Причина
Неформальные/неявные диапазоны являются источником ошибок.
Пример
X* find(span<X> r, const X& v); // найти v в r
vector<X> vec;
// ...
auto p = find({vec.begin(), vec.end()}, X{}); // найти X{} в vec
Примечание
Диапазоны чрезвычайно распространены в коде на C++. Как правило, они неявны, и обеспечить их правильное использование очень сложно. В частности, для пары аргументов (p, n), обозначающей массив [p:p+n), в общем случае невозможно узнать, действительно ли есть n элементов для доступа после *p. span<T> и span_p<T> — простые вспомогательные классы, обозначающие диапазон [p:q) и диапазон, начинающийся с p и заканчивающийся первым элементом, для которого истинно условие, соответственно.
Пример
span представляет диапазон элементов, но как манипулировать элементами этого диапазона?
void f(span<int> s)
{
// обход диапазона (гарантированно корректный)
for (int x : s) cout << x << '\n';
// обход в стиле C (потенциально проверяемый)
for (gsl::index i = 0; i < s.size(); ++i) cout << s[i] << '\n';
// произвольный доступ (потенциально проверяемый)
s[7] = 9;
// извлечение указателей (потенциально проверяемое)
std::sort(&s[0], &s[s.size() / 2]);
}
Примечание
Объект span<T> не владеет своими элементами и настолько мал, что может передаваться по значению.
Передача объекта span в качестве аргумента столь же эффективна, как передача пары аргументов-указателей или передача указателя и целочисленного счётчика.
Смотрите также: Библиотека поддержки
Контроль
(Сложный) Предупреждать, когда обращения к параметрам-указателям ограничены другими параметрами целочисленных типов, и предлагать использовать span.