#опытным
Рэнджи - это не просто сахар и "уродливые" палки pipe-синтаксиса, как думает некоторая часть плюсовиков. Это еще и в том числе про скорость и выразительность.
Возьмем пример из прошлого поста:
std::string text = "one two three four";
std::vector<std::string_view> strs;
boost::split(strs, text, boost::is_any_of(" "));
Чтобы разделить всю строку на по пробелам, нужно создавать отдельный вектор. А это как минимум одна аллокация. Плюс на расширение вектора уйдут аллокации, плюс алгоритм сам может выделять память.
И на самом деле мы получаем кучу аллокаций.
Ну а что если нам нужна только третья подстрока? Каким бы красивым и проверенным не был бы вызов boost::split, он будет делать лишнюю работу + выделять память.
Можно конечно самим написать решение с циклом или подряд использовать std::string::find и это будет работать. Но там нужно аккуратно работать с индексами, желательно еще и отдельно тестировать этот код.
Но можно поступить проще и воспользоваться ренджами!
Рэнджи ленивые. Прям как студенты: всем на последнем курсе заранее дают задачу написать диплом, но обычно его начинают писать, когда научрук уже дает последнее китайское предупреждение вслед за пендалем, что нужно сделать работу уже вчера.
Но у рэнджей это скорее преимущество.
Пока у диапазона не спросишь следующий элемент - он его не вычислит. И в этом прелесть.
Мы просто пишем:
auto range = text | std::views::split(' ');И абсолютно ничего не происходит! Но мы декларируем, что хотим получить поддиапазоны исходного текста, которые получены разбиением по разделителям.
С помощью ренджей мы даже можем оставить конкретный интересующий нас поддиапазон:
auto range = text | std::views::split(' ') | std::views::drop(2) | std::views::take(1);Отбрасываем первые два элемента и берем только первый оставшийся. И опять же, ничего не происходит.
Вычисления происходят, когда мы пытаемся что-то узнать о результирующем диапазоне, например, пустой ли он:
if (range.empty()) {
std::cerr << "There are less than three words in text";
}Если итоговый поддиапазон непустой, то в нем должен быть лишь один элемент, являющийся поддиапазоном оригинальной строки. То есть по сути легковесный view на нужную подстроку:
std::string_view str{*range.begin()};
std::cout << str << std::endl;
// OUTPUT: threeИ здесь нет ни одной алллокации! Чисто работа с поддиапазонами. Это ровно то, чтобы мы бы делали руками через find, только в понятном декларативном стиле.
Возможно find работал бы и быстрее(а это еще проверить надо), но рэнджи предлагают более понятную альтернативу самописному коду.
Be expressive. Stay cool.
#cpp20