Pull to refresh

Comments 36

Спасибо за статью, тема ranges не частый гость на хабре.
Не могли бы вы уточнить, что вам не нравится в коде, который упомянут в заключении? Да, ваш вариант короче, но при чём здесь эффективность? Алгоритмическая сложность одинаковая, особого оверхеда я тоже не вижу. В чём проблема?
Более того, с учётом реализации any_of, предложенной выше, она ещё и медленнее. Она перебирает все элементы, а не останавливается на первом удовлетворяющем, как цикл. Так что зависит от реальных данных, а на общий случай нужны как минимум бенчмарки.
Вы правы, в данном случае эффективность даже хуже. Я имел в виду, что бывают ситуации, когда неопытные программисты пишут range-based for там, где без него можно обойтись, из-за его простого синтаксиса, вследствие чего помимо лаконичности может ухудшится и эффективность, хотя последнее происходит довольно редко. Извиняюсь за заблуждение.
Ну так неопытные напишут ещё и не то…

Ога, приводите при этом неэффективный код, подталкивая неопытных к тому, чтоб писать неэффективный, хоть и лаконичный код.

а можно, пожалуйста, пример, когда range-based for будет менее эффективен, чем альтернативы?
вспомнились слова песни «А козак чує — серденько мре.»
На C++ не пишу, но с замиранием сердца читаю новости про расширение стандарта. Кто всё это сможет объять?
Конкретно рэнджи — просто улучшения удобности и юзабельности стандартной библиотеки алгоритмов. Для конечного пользователя ничего сложного нет — просто меньше бойлерплейта и больше выразительности.

Не думаю что причитания про необъятность стандарта уместны как минимум в этом вопросе.
Сегодня — да, необъятность является приувеличением.
Однако темп, который взял комитет, заставляет задуматься, сколько абстракций будет в C++ через 10 лет.
Наверное так просто кажется на фоне того застоя, который имел место быть в конце 90х и 00х. Другие языки тоже активно развиваются и обростают фичами, просто там частые и постоянные релизы, что дает ощущение бесшовности.
На C++ не пишу, но с замиранием сердца читаю новости про расширение стандарта. Кто всё это сможет объять?

ИИ написанный на java? ;)

Завершение статьи, конечно, фееричное:


Я ненавижу range-based цикл for, потому что он мотивирует людей писать его везде где нужно и где не нужно, из-за чего зачастую ухудшается лаконичность кода

Стандарт словно движется в сторону Java Streams или LINQ. А ценой лаконичности будет понижение производительности, когда неофиты набегут и будут совать это везде

О, я не один такой в мире! Тоже пользую такой многословный цикл, ещё со времен басика в начале 90-х :). Зато наглядно.

К нему кроме многословности ещё вопросы возникают.
ranged-for оперирует началом, концом и оператором ++.
Хочешь — запускай для вектора; хочешь — для списка или вообще собственного контейнера.
Но если контейнер, например, банальный вектор. И операция — удвоить всего его элементы — то за абстракцией ranged-for скрывается возможность поделить его на 8 частей и запустить операцию параллельно на 8 ядрах процессора. Потому что "8 частей" никак не вытащить из примитивов начало, конец и инкремент.

А я не люблю range-based for за то, что он связывает синтаксис языка с определениями методов begin() и end(), которые являются по сути вторичными по отношению к синтаксису, но теперь попадают в некий раздел особых сущностей, как бы недоключевые слова. Это сломало красоту C++, в котором до этого не было таких особых случаев.

Тем не менее, я ими (циклами) пользуюсь. Всё таки сахар они, зараза, сладкий ) Даже синтаксический. Но, конечно, только там, где это не бьет по эффективности.

Только в отличие от Java и C# всегда можно будет фоллбэкнуться до эффективной реализации, не меняя контекст языка. Когда этот цикл станет бутылочным горлышком — ну ты пойдешь и заоптимизируешь, а пока так.

Ну за Java не скажу, а в C# если отправной точкой считать LINQ (как это часто бывает), то фольекаться тоже есть куда.

Мне кажется, заголовок немного не соответствует теме. В стандарт вводятся именно range-v3, а большинство примеров на think-cell, что может немного вводить в заблуждение.
Не спорю, что в стандарт планируют ввести Range V3, однако у think-cell есть множество оптимизаций, поэтому их библиотека тоже стоит внимания.
Вот серьезно, мне кажется в комитете стандарта С++ не хватает мужика с пулеметом, который бы расстрелял всех к чертям.
объединив итераторы на начало и конец вектора в один объект

А сам объект вектора не является тем самым объединением? Ей-богу, более уродливого синтаксиса и api чем в С++ найти невозможно…

Нет, не является. Тогда было бы возможно иметь только один интервал.

почему это? вектор вполне себе может являтся интервалом, который включает в себя весь вектор. А вот если вам нужен интервал вектора со 2-го по 15-й элемент, то юзайте, пожалуйста, отдельный range.

на самом деле, эта концепция уже очень хорошо развита в Питоне, особенно прикольно то, что генераторные интервалы делают вычисления генерируемых последовательностей «ленивыми».

но как таковая эта концепция не является чем-то новым в мире метапрограммирования, просто тема актуализировалась тем, что её хотят стандартизировать.
хотелось быть первым, кто откомментит про range в python...))
Имелось в виду рассматривать итераторы на начало и конец непосредственно как одно целое, а не как два разных итератора (то есть создать view), но и объект вектора (как и все контейнеры) тоже считается интервалом, об этом я написал далее.
Range/Intervals — следствие дизайна STL им. математика Степанова, идея которой, как известно, пришла в делириуме после отравления рыбой.

Большинство техник на большинстве архитектур исторически базируется на применении адреса и счётчика, включая hardware. Например DMA или инструкции REP MOV (x86) или LDIR (z80). Я помню только одну подобную технику — её использовали процедуры «монитора» Радио-86РК и «Специалист». Они тоже копировали данные с указанием адреса первого и последнего байтов блока. Не адреса за блоком, как это делает STL, а именно последнего. Это может быть иногда удобно при ручной работе с командами копирования блоков памяти, но неудобно (и медленно) при непосредственном программировании.

Сама семантика структур данных естественного мира в подавляющем большинстве случаев основывается на предположении количества элементов, а не на указании последнего.

При этом большинство библиотек/реализаций/high-level языков программирования предоставляет массивы/контейнеры хранящие свою длину. Для них не требуется указывать начало-конец контейнера, указывается только его имя (а также если необходимо — смещение и длина).

Так что это не «будущее», а очередная заплатка на неудобный/ошибочный/freaky дизайн. Многие заплатки Modern C++ — синтаксический сахарок, не привносящий actual value.
Да! А ещё функциональный анализ не нужен для того, чтобы в магазине отсчитать нужное количество бутылок пива и расплатиться за это. Так что и его в топку его, Зина!
пришла в делириуме после отравления рыбой

это многое объясняет!

Не могу согласиться "в подавляющем большинстве". Если уж про то говорить, то в интернете в подавляющем большинстве находятся сайты, написанные поверх базы данных (готовой или самописной), а размер ответа запроса от той базы данных может не знать никто. Можно селектнуть из nosql базы итератор на ответ совершенно неясного размера, там может быть десять терабайт данных в хвосте запроса. Более того, сейчас уже нормально, что ответ этот может меняться, в той части, которую клиент ещё не видит, и с ним могут происходить разные другие трансформации. Для этого нужен крайне ленивый асинхронный API, такие операции поддерживающий.


Мне кажется, тут есть некая большая проблема в видении языка. Разработчики стандарта думают о C++ как об универсальном языке для всего на свете — не менее универсальном, чем джава, сишарп или питон, но с другим набором стартовых предположений и трейдоффов. Но есть парочка узкоспециализированных категорий разрабов, например эмбеддед и геймдев, которые считают что C++ — их личный язык и никого другого они рядом не потерпят. И вот тут начинается великая битва :)

Мне кажется, тут есть некая большая проблема в видении языка. Разработчики стандарта думают о C++ как об универсальном языке для всего на свете — не менее универсальном, чем джава, сишарп или питон

«строго более» универсальном. Всё-таки с++ применим еще и там, где интерпретаторы/вм либо не работают, либо работают недостаточно быстро.
UFO just landed and posted this here
Но если использовать трансформирующий адаптер (transform adaptor), то всё выглядит гораздо более лаконично:

Да как-то не увидел я там лаконизма: примерно одинакового размера фрагменты. Меня как-то вот эти фильтры и адаптеры не радуют. Да, я прекрасно помню, как использовать bind(), men_fn() и тому подобное, но в эпоху до C++11 выбор обычно был между «собери предикат из готовых кусков» и «пиши отдельную функцию/функциональный объект». Когда появились лямбды, стало возможно прямо на месте чётко выразить, чего хочется. А теперь вы предлагаете опять собирать простой и ясно выглядящий критерий вида «a.id == 4» из каких-то кусков, которые читающему ещё расшифровывать надо. Попробуйте заменить мысленно выражение под оператором if() таким вот кодом. Никто же так не пишет, и неудивительно.
допустим, у вас есть алгоритм, состоящий из 3-7 «кирпичиков». Когда код написан на циклах/if'ах (по 1-2 на алгоритм), читающему сначала придется разобраться, что делает каждый из этих циклов. Назначение алгоритмов же понятно по их общеизвестным именам. Сейчас у кода с алгоритмами есть синтаксический оверхед из-за итераторов и лямбд, но в ranges итераторы нужны намного реже.

Из моего опыта, код на нынешних алгоритмах в среднем значительно короче. Просто это плохо заметно на совсем тривиальных примерах, как в статье.
Да, понимаю. Но я и не ратую за циклы и if-ы, мне не нравится попытка заменить лямбды предикатами, склеенными из стандартных функций. Вот эта штука плохо читается.
Sign up to leave a comment.

Articles