Comments 25
std::vector<int> vec = {1, 2, 3, 4, 5, 3};// Manually remove all occurrences of 3
for (int &num : vec) { if (num != 3) {
result.erase(&num);
}}
result -> vec
Если две тройки будут идти друг за другом, удалится только одна.
Или вообще программа вылетит с ошибкой.
Спасибо за статью! Вы, вероятно, не особо рассчитывали на читателей с другим стеком... но некоторые из них тоже с большим удовольствием прочитали ;-)
Я вот, например, пишу только на фортране... Но, поглядывая одним глазком на примеры, а другим - на свои массивные операторы, сечения массивов и элементные функции, не мог не порадоваться, что мне в большинстве перечисленных случаев вообще никакие библиотеки не нужно знать. Почти все есть готовое в языке. Причем большая часть - аж с 1990 года ;-)
Вообще, чем больше читаю статей про плюсы, тем упорнее убеждаюсь в своем заблуждении, что современный фортран позволяет дебилам вроде меня писать столь же эффективный и читаемый код, который на других языках подвластен лишь программистам с определенной квалификацией ;-)
А теперь мне еще и стало понятно, почему фортран, несмотря на все свои фичи, постепенно выходит из моды (на самом деле нет - но лишь в своей достаточно узкой нише). Сказано же: создай инструмент, которым сможет пользоваться даже дурак, и только дурак захочет им пользоваться
;-))))))))))))))))))))))))))))))))
А если чуть-чуть серьезнее, пойду покопаю фортрановские библиотеки. Так как для отдельных примеров я с ходу прямого аналога не сообразил.
А злые языки поговаривают, что под капотом
базовые библиотеки у фортрана и си одинаковые, причем с очень древних времен и до наших дней. Только интерфейс разный. А значит, где-то в их глубине аналоги должны обнаружиться ;-)
Я, видать, из те же дебилов. В давнее время в пилотской среде был анекдот: "Зачем в боинг 747 такой выступ сверху?" - "Чтобы капитану было куда класть свой бумажник".
Так вот, смотря на все это переусложнение современных средств разработки у меня создается впечатление, что они нужны в первую очередь для оправдания зарплат тех, кто в этом хоть что-то способен понять. В то время как на качестве продукта это не особо сказывается (дальше долгая стандартная дискуссия, пропустим).
Я не в игровой области программирую, но опыт непрерывного программирования в разных ЯП и разных стилях у меня уже больше 30 лет. И знаете что, когда меня на собесах пытались вот таким образом поддеть, я сразу таких собеседующих посылал в пеший поход. Да, код без всех этих библиотечных лямбда наворотов будет немного более распухшим и может быть не столь современно выглядящим, но зато он куда более читаем и контролируем для постороннего взгляда, и в целом куда меньше зависит от ошибок, которые могут быть в библиотеках. Да, несомненно, я могу своих наляпать по пути, но ведь и нет гарантий, что я не сделаю их при использовании всех наворотченных библиотек.
Я вовсе не консерватор, и вполне себе пользуюсь всем новинками, которые мне удобны, но явно не на стадии собесов. Если тот или иной фреймворк или библиотека является внутренним стандартом, то уже после выхода на работу я его освою, и скорее всего разберусь благодаря обширному опыту куда глубже, чем тот кто нахватался по вершкам и знает только эту пару библиотек и все. Если тестирующий на отборе смотрит только на такие моменты, то он скорее всего пропустит реального разработчика, и потом в случае малейшего затруднения отобранный сотрудник просто не будет знать куда двигаться, ибо он сидит в одной парадигме изученной по нескольким библиотекам.
автор статтьи показывает стандартные огрехи с промахами, если начать пробовать вы столкнётесь с более нормальными ошибками даже в 2д - если выбор будет С++, как бы будет наглядно по ресурсам по памяти, в каких ситуациях не плохо работает (библиотеки определены стеком и сферой и сложностью написания их с нуля если есть желание поидее, причем этот выбор может продолжаться до движков, которые уже реализованы )
кстати связка functional + lambda нагляднее работает чем адрес функции в С - мне почему-то понятнее конктрукция functional + lambda, и я легко могу прозивать адрес функции и вот такие нюансы в коде типо,
Скрытый текст

простенький пример - низкополигональная анимация, тест на С++ не на движке, далее как пример посмотрим нагрузку на проц, и в диспетчере,
(в диспетчере 0.80 CPU, зато в граффике вижу как летит местатми нагрузка в сам момент кадра, это один из примеров типо вот я посмотрел, а дальше всё это фиксить )
тоесть кадра не совсем прям от окна, потомучто теперь время + еще на интерполяции скелета во время анимаций!
Так и я не к статье в целом писал своё мнение, а к началу, где про вопрос на собесе. Краткость, не всегда показатель таланта, так сказать. И судить об уровне, только по применению или нет тех или иных библиотек или наворотов, да особенно когда не сказано, что нужно применить те или иные инструменты - не всегда правильный подход.
Опять же - я не против всех нововведений в С++, сам пользуюсь, когда пишу на нем. Но не ставлю самоцелью, так как код все равно становится мало читаем. ПО крайней мере, лично для меня, так как я привык к старой парадигме и приемам. Консерватизм, если хотите. Но опять же, без фанатизма. Ничто не стоит на месте, тем более в нашей отрасли.
и ещё - "небезопасный код" и его ошибки от которых все эти "облегчатели программирования" пытаются уберечь своими подпорками, такие как NPE, вылет за границы массива и прочее подобное, как раз и есть индикаторы пригодности кода. если код написан криво то они проявятся и просигналят о том что алгоритмы работают не так как автор задумал. а вот если они будут демпфированы всеми этими "облегчалками" то некорректная работа кода уйдёт дальше попадёт в прод и может вылезти только через годы эксплуатации таким геморром что мало не покажется никому или вообще превратится в неуловимый баг.
а про собеседования тоже согласен - такое чувство что в нынешнее время ценится не умение программировать а знание как можно большего количества синтаксического сахара.
эти алгоритмы в идеале просигналят только в С, потомучто помимо самого сахара, в С++ очевидные вещи могут быть индивидуально реализованы в этом суть, поэтому и базу спрашивают и синтаксический сахар поидее
а С++ поидее имеет документацию к его реализациям, поэтому могут спрашивать только синтаксический сахар, ведь вектор может быть уже нечевидным, когда обзором базового вопроса мог быть односвязный список (отсюда нюансы какой односвязный список - шаблоны, не шаблоны, или пример на gcc С)
в случае эксцепшена, сложнее искать где он вылез. и дебажить сложно такие алгоритмы.
По части "оптимальной реализации", загнал первый пример в Годболт:
https://gcc.godbolt.org/z/8KhPxe1M4
рукописный код векторизует, STL-ный - нет. Мало того, STL ещё и считает сумму в плавающей точке.
интересный вы человек.. в чем попросили, в том и считает)
Хоть я не очень разбираюсь в асме, но и с флоатом тоже векторизован? не? А с интом асмы вообще одинаковые
Я не настоящий плюсовик :) И правда, там же 0.f. Автор статьи ошибся, а я скопипастил, сходу не разглядев.
С интом да, всё отлично. C флоатами странная ситуация, почему-то и ручную реализацию не хочет векторизовать, пока не пнёшь специальной директивой. https://gcc.godbolt.org/z/7qqhcq6ox
В окне Opt Viewer раньше писал причину, почему нет, сейчас ничего внятного не пишет.
vaddss хотя и относится к AVX, но это скалярная команда, векторная будет vaddps. Да и видно, что счётчик цикла наращивается на 4, на 1 флоат/инт.
Единственное полезное применение std::for_each
- это вместе с std::execution
. Все остальное хуже, чем обычный цикл for.
Забавное наблюдение, заняло 1 минуту на проверку:
Аналогично for, но более выразительно и с меньшим количеством кода.
Цикл - 149 символов. Выразительный и с меньшим количеством кода - 206
Посмотрите пример с кешем шейдеров, я для этого его там выложил. А так да, символов меньше. Но и программы, что выводят хелло ворлд не так что бы востребованы
а зачем сами шейдеры мержить?
https://www.reddit.com/r/opengl/comments/1c2yrct/how_to_use_gl_arb_shading_language_include/
Так давайте проверим, алгоритмы говорите, читабельные говорите и все такое блабоабла.
auto xxx(auto& x, auto& y){
using namespace std::ranges;
auto begin = find_first_of(x, y, not_equal_to{});
auto end = find_first_of(subrange(begin, x.end()) | views::reverse, y, not_equal_to{}).base();
return subrange{ begin, end };
}
Назвались груздем полезайте в кузовок. Рэнджи ещё более самые супер пупер лучшие алгоритмы, авто везде не просто так, а что бы алгоритм был максимально дженерик и компилятор/рэнджестроители могли показать максимальную оптимизацию под конкретно ваш случай. Там конечно можно ещё концептов на х, у навесить для пущей пидидитости, но это только добавит шума и не облегчит ответ на вопрос. Что делает эта функция одним словом? Я специально заменил нормальные имена на х, у ибо тогда станет очевидно.
Гусары не читерить, ллмы трёх метровой палкой не трогать. В идеале сипипиреф тоже не открывать если вы за алгоритмы должны и так понять.
Вопрос со звёздочкой насколько производителен такой код? Годен для геймдева?
это strip?
то есть для x: "1123456111" и y: '1' вернёт "23456"?
PS. Ну почти) я не знал что find_first_of принимает две последовательности. Тогда просто вместо y тоже может быть "123" и тд.
Ну можно и так сказать, но есть более общеупотребительное слово, вы сразу поймете о чем речь если типом х и у будет строка. Я просто взял простой и понятный код и переписал на рэнджи. Потом для проверка попросил кита подумать и объяснить что делает код, умный гад, думал долго, но ответил правильно, но что ещё важнее он показал, что моя прямая попытка смапать на рэнджи работает не совсем так как оригинальный код. В оригинале find_first_not_of, что не тоже самое что и в примере выше. Работает правильно если у содержит 1 элемент, но в оригинале у меня стандартный набор элементов для этого алгоритма в качестве дефолта идет. А написать на рэнджах правильно низя т.к. нету там find_first_not_of. Не подвезли даже в с++26. Можно конечно извернуться и написать через find_if_not + contains/any_of или find_first_if + none_of, но и так уже сложно читать.
в std еще интерсект есть
я к тому что если у вас задача на коллизию точки то поидее стд интерсектом можно наверно
https://en.cppreference.com/w/cpp/algorithm/set_intersection
Если писать плохой код, то он будет плохим
И даже в таком виде сразу понятно что делает этот код, для сравнения можете на циклах то же самое написать и там будет что то ну очень неприятное с поиском по ренжу
Насчёт производительности - ничего лишнего этот код не делает
Пример с copy_if
Кратче тут в смысле количества строк, по количеству символов скорее нет чем да
Алгоритмы это хорошо, но пример не тот. Вообще синтаксис плюсов к сожалению - это больно. Рациональность упрощения синтаксиса начинается либо когда используется что-то сложное в реализации, типа partishn-нов. Либо когда код не надо сильно оптимизировать. Циклы то никуда не исчезают и проход по ним идёт, и часто когда время ценно, в одном цикле ищется и минимум и максимум и среднее и еще штук 5 параметров.
Любовь к лямдам, часто приводит к копи паст, вместо написания функции.
В 25 году уже пора использовать интервальные алгоритмы, просто v вместо этих бесконечных v.begin(), v.end().
Game++. Juggling STL algorithms