Кресты / Говнокод #27412 Ссылка на оригинал

0

  1. 1
std::ranges::for_each(tasks, [](auto x) {x();});

а ещё теперь не нужно писать std::begin(), std::end().
c++ будущего.

Запостил: digitalEugene digitalEugene, (Updated )

Комментарии (205) RSS

  • Почему бы не просто for (auto& task : tasks) task()? Работает уже лет 10 и рейнджи не требует.
    Ответить
  • Зачем придумали ranges, а не ещё одну перегрузку, которая умеет брать begin, end?
    Ответить
    • ranges разрабатываются для решения оснявной проблемы begin и end — нявозможности чейнинга итерирующих функций. Классические ФП-like цепочки, вроде "collection.filter {it % 2 == 0}.map {it * 2}.take(5)", ня крестовых итераторах принципиально нявозможно няписать, не изобретая ленивых генераторов (то есть половины ranges).
      Ответить
      • можно сделать как в питоноячьем говне через функцию, котоаря принимает итератор и лямбду или указатель на фукнцию

        но ленивости (генеаторов) всё равно не будет из коробки, угу
        Ответить
        • Чейнинга всё равно так просто ня получится. А если получится — у тебя уже будет криво и косо реализована половина ranges-v3.
          Ответить
          • угу, но его и в питоне нет, к сожалению.

            можно как-бы сделать (псевдокод)
            take_first(10, sort(&sorter, petuhi.begin(), petuhi.end()))

            будет как питон с его map и прочим itertools

            но в питоне есть генераторы, а тут нету, и если питухов 100000 то багор
            Ответить
            • ФП в Питоне — отвратительное фу, ня него равняться ня нужно.

              > take_first(10, sort(&sorter, petuhi.begin(), petuhi.end()))
              Только тут же возникает проблема: что возвращает sort() и что принимает take_first()? В итераторном коде сигнятура take_first() выглядела бы примерня как "(void) take_first(size_t count, It begin, It end, OutIt outBegin)", и в неё sort() някак ня впихнуть.

              А вот благодаря миксиняшкам такие проблемы решаются тривиальня.
              Ответить
              • принимала бы она коллекцию, и получала от нее begin

                но это всё не лениво, а значит весьма сомнительно
                Ответить
                • > принимала бы она коллекцию, и получала от нее begin
                  Так вот имення чтобы ня принимать коллекцию и делались итераторы. Чтобы ты мог, няпример, легко и просто отсортировать половину коллекции: "std::sort(collection.begin() + collection.size() / 2, collection.end())".

                  А ещё так нячинают возникать проблемы: а что, если я хочу получить из sort() ня vector, а, няпример, list? А что делать с кастомными аллокаторами? А что, если я хочу в take_first засунуть map, а получить vector? И так далее.
                  Вот чтобы таких проблем ня было — и придумали итераторы. Ты сам создаёшь контейнеры, которые тебе нужны, а функции оперируют только няд итераторами. Но, как показала практика, это была далеко ня самая лучшая идея.
                  Ответить
                • > принимала бы она коллекцию, и получала от нее begin
                  Так вот имення чтобы ня принимать коллекцию и делались итераторы. Чтобы ты мог, няпример, легко и просто отсортировать половину коллекции: "std::sort(collection.begin() + collection.size() / 2, collection.end())".

                  А ещё так нячинают возникать проблемы: а что, если я хочу получить из sort() ня vector, а, няпример, list? А что делать с кастомными аллокаторами? А что, если я хочу в take_first засунуть map, а получить vector? И так далее.
                  Вот чтобы таких проблем ня было — и придумали итераторы. Ты сам создаёшь контейнеры, которые тебе нужны, а функции оперируют только няд итераторами. Но, как показала практика, это была далеко ня самая лучшая идея.
                  Ответить
                  • почему не лучшая?

                    имхо, итератор это хорошо, просто небыло красивых средств для ленивости, и потому половина функционала была недоступна..

                    а вот твой пример с /2 отлично работал же, да и независящие от контейнера алгоритмы -- тоже
                    Ответить
                    • 1. Отсутствие ленивости. Как результат — в любой цепочке длиннее одного действия няобходимость ломать мозги над тем, как бы все вычисления провести in-place.
                      2. Отсутствие чейнинга. Тут всё и так понятно: вместо няшного sort().filter().map().reduce() приходится писать гигантские вербозные портянки.
                      3. Няобходимость в std::(back_|front_)?inserter для вставки результата в изнячальня пустой/маленький контейнер.
                      4. Общая высокая вербозность, особення в базовых (в том числе и самых распространённых) случаях. Вместо collection.sort() / sort(collection) — sort(collection.begin(), collection.end()).
                      Ответить
                      • > вербозность

                        Особенно сраная пара remove/erase, про которую так любят спрашивать на собеседованиях.
                        Ответить
                        • А это уже ваша плата за знание устройств коллекций и того факта, что вектор и лист устроены по разному

                          один питух двигает говно, а второй чистит вилкой освободивщееся место если я верно помню
                          Ответить
                          • Только для листа remove из алгоритмов применять не рекомендуется. У него есть свой, особенный remove/remove_if, который делает тоже, что и пара remove-erase для остальных контейнеров.

                            К — Консистентность.
                            Ответить
                      • >Отсутствие ленивости.
                        да, это отсос. В руби я могу сделать цепочку от 0 до бесконечности, и выбрать из нее по условию первые N элементов, а тут фиг

                        >Отсутствие чейнинга.
                        угу( ну вот это как раз как в питоне тоже, и это плохо. А вот в руби... ну ты понял)

                        > std::(back_|front_)?inserter
                        А иначе как контейнер расширится?

                        Итератор в векторе или массиве же это просто указатель на элемент ЗА хвостом, верно?

                        Как же можно сделать так, чтобы при писании туда вектор бы расширялся?

                        >Общая высокая вербозность
                        Угу(( но без итераторов было бы еще вербознее
                        Ответить
                        • > А иначе как контейнер расширится

                          Ну вот поэтому range -- это более красивая концепция чем итератор.
                          Ответить
                          • я не спорю, что range это круто

                            но и итератор на момент с03 тже было круто имхо
                            Ответить
                        • > А иначе как контейнер расширится?
                          А в ranges вообще ничего ня надо расширять. После серии преобразований ты получаешь ленивый генератор, который вообще някуда записывать ня надо: ты можешь итерироваться сразу по няму.
                          Но даже если вдруг понядобилось материализовать — ты просто пишешь условный ... | ranges::to<std::vector> и получаешь всё в лучшем виде.
                          Ответить
                    • > независящие от контейнера алгоритмы

                      Да это миф, на самом деле. Я вот сходу даже не назову алгоритм, который ну совсем прям на любом контейнере работает.

                      Везде или какие-то подвохи с вычислительной сложностью std::find(map.begin(), map.end(), x) vs map.find(x) или какой-то постпроцессинг в духе v.erase(std::remove(v.begin(), v.end(), x), v.end()) нужен.
                      Ответить
                      • > ну совсем прям на любом контейнере работает

                        Ну, они обычно РАБОТАЮТ. Стоит ли так работать, или нет — это другой вопрос.
                        Ответить
                      • алгоритм итерируется по контейнеру и выводит его значения. Он более ли менее годно работает на всех контейнерах

                        просто итераторов бывает много разных: кто-то поддерживает арифметику, кто-то поддерживает запись, итд
                        Ответить
                        • > на всех* контейнерах

                          * На всех кастомных контейнерах, которые косплеят соответствующий стандартный.

                          А поскольку в стандартной либе все контейнеры разные, каких-то общих алгоритмов у них очень мало получается. По сути каждый алгоритм под что-то конкретное нужен. И во многих местах вместо них надо брать кастомную версию из самого класса и т.п. Консистентность на высоте.

                          Короче не особо взлетела эта идея, имхо.
                          Ответить
                          • ну блин, чудес не бывает: никто не обещал вроде что ВСЕ алгоритмы будут подходить ко ВСЕМ контейнерам

                            Это был бы булщит уровня "локальный вызов заменим удаленным вызовом по HTTP, а алгоритм останется тем же" (над этим еще Фаулер ржал в 2003-м), но какие-то алгоритмы всё таки можно переиспользовать
                            Ответить
                            • > но какие-то алгоритмы всё таки можно переиспользовать

                              А какие? Ну вот банальный find. Он работает, по сути, только на листе и не отсортированном векторе. Для мапы/хешмапы надо брать их реализацию, которая за логарифм ищет. А для отсортированного вектора есть binary_search, который на отсортированном листе бесполезен.

                              Так и живём.
                              Ответить
                              • блин, ну вот у меня есть forward iterator который умеет ++ и разыменовываться, так?

                                Я пишу алгоритм, который итерируется по нему и выводит значение если оно полдходит по условию. Что не так?


                                Про find: с этим даже джависты отсосали: там вроде поиск в массиве работает только если он сортирован, именно ради бинари сёч

                                но если мне похуй на перфоманс, я могу написать поиск за O(N) и он будет работать на чем угодно, не?
                                Ответить
                                • > но если мне няк на перфоманс, я могу написать поиск за O(N) и он будет работать на чем угодно, не?
                                  Но тогда теряется смысл в специализированных контейнерах. С тем же успехом можня хранить всё в std::vector.
                                  Ответить
                                  • >но тогда проёбывается смысл в специ

                                    А вдруг я ищу что-то в алгоритме раз в 10 лет, а всталяю в середину каждые 1ms, и тогда мне важно взять именно list?
                                    Ответить
                                • > который итерируется по нему и выводит значение

                                  Ну ок, transform/copy действительно для всех контейнеров работают (на входе). Целых джва алгоритма уже нашли!
                                  Ответить
                                  • all/any/none_of
                                    форич/_н
                                    count/count_if
                                    mismatch
                                    adjacent_find
                                    search/_n
                                    Все что требует не лучше ForwardIterator
                                    Ответить
                                    • > search

                                      search (не путать с find!) на мапе или хешмапе очень полезен, конечно... Хотя иногда что-то и найдёт, наверное.
                                      Ответить
                                      • На хешмапе найдёт только случайно, согласен, а на мапе/сете будет работать, если рассматривать его не как ассоциативный контейнер а отсортированную последовательность. И искать не просто совпадающую последовательность (это делается upper/lower_bound), а какую-то эзотерическую хуйню при при помощи предиката.
                                        Ответить
                                    • > count
                                      std::multimap<std::string, std::string, std::less<>> a{ {"hello", "world"}, { "hello", "you" } };
                                      size_t hello_count = std::count(a.begin(), a.end(), "hello");

                                      (╥﹏╥)
                                      Ответить
                                      • std::vector<std::pair<std::string, std::string>> foo a{ {"hello", "world"}, { "hello", "you" } };
                                        size_t hello_count = std::count(a.begin(), a.end(), "hello");

                                        (╥﹏╥)

                                        Действительно плохой алгоритм.
                                        Ответить
                                        • std::multimap<std::string, std::string, std::less<>> a{ {"hello", "world"}, { "hello", "you" } };
                                          size_t hello_count = a.count("hello");

                                          Это просто ещё один пример потёкшей абстракции.
                                          Ответить
                                  • Так а что ты предлагаешь всё таки?

                                    Спрятать алгоритмы в сами контейнеры, потому что независящий от контейнера алгоритм часто просто не написать?


                                    А мне вот нравится, что у вектора и умассива общие алгоритмы, а в джаве -- нет..
                                    Ответить
                                    • Просветлённые джависты обычно стримы используют, см. ссылку ниже.
                                      Ответить
                              • > А какие? Ну вот банальный find. Он работает, по сути, только на листе и не отсортированном векторе.

                                А вот взять например метод sort, который есть у std::list и у std::forward_list. А у вектора никакого метода sort нет, используйте std::sort.
                                Зачем? Зачем? std::sort требует random access iterator и поэтому для std::list и std::forward_list нельзя std::sort, а для std::vector можно? А почему тогда не сделать так, чтоб и у std::vector был метод sort, ну, типа для единообразия?
                                Ответить
                                • Вообще контейнеры в крестах какое-то говно. Вот взять опять-таки std::forward_list (в простонародье известен как "односвязный список"), в нем нет метода push_back. Почему? Ответ вероятно будет "потому что это сложно, надо прошагать в самый хвост односвязного списка и потом вставить, это оооочень долго". Эмм, ну допустим, а с хренов каких у std::vector есть метод insert? Ведь следуя такой логике, никакого insert там быть не должно, insert в начало длинного вектора это охренеть как долго. И да, у std::vector есть insert, но нет метода push_front. Где логика? Кто и на каком основании так это спроектировал?
                                  Ответить
                                  • http://stolyarov.info/books/programming_intro/about.html

                                    > Учителям такой категории вообще, судя по всему, всё до лампочки: в C++ используется библиотека STL, а значит, надо рассказать ученикам STL; разумеется, дальше vector'а и list'а обучение никогда не заходит (при этом эти два контейнера, пожалуй, самые бесполезные из всего STL), но самое интересное, что ученики, разумеется, так и не понимают, о чём идёт речь. В самом деле, как можно объяснить разницу между vector и list человеку, который никогда в жизни не видел ни динамических массивов, ни списков и вообще не понимает, что такое указатель? Для такого ученика list отличается от vector тем, что в нём нет удобной операции индексирования (почему её там нет? ну, нам что-то объясняли, но я ничего не понял), так что вообще-то всегда надо использовать vector, ведь он гораздо удобнее. Что? Добавление в начало и в середину? Так оно и для вектора есть, какие проблемы. Ну да, нам говорили, что это «неэффективно», но ведь работает же! Переучить такого ученика практически нереально: попытки заставить его создать односвязный список вручную обречены на провал, ведь есть же list, а тут столько ненужного геморроя! Собственно говоря, всё: если нашему обучаемому дали в руки STL раньше, чем он освоил динамические структуры данных, то знать он их уже не будет никогда; путь в серьёзное программирование ему, таким образом, закрыт.
                                    Ответить
                                    • Учить нячиняющих программистов C++ — крайне тупая идея. Кресты слишком далеко ушли от железа, чтобы студенты няучились понимать низкоуровневые абстракции (в том числе и указатели), но при этом они слишком ужасны, чтобы ня них можня было показывать высокоуровнявые концепции (от алгоритмов и до паттернов).
                                      Имення поэтому учить программированию нядо с C.
                                      Ответить
                                      • ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня ня
                                        Ответить
                                      • Или с «Nim», там есть как высокоуровневые абстракции, так и адресная арифметика. А может быть и нету, на самом деле я ещё ня выучив «Nim», мяу uwu
                                        Ответить
                                      • плюсану

                                        хуже только сразу учить их на каком-нить питоне или JS.

                                        В случае крестов они хотябы будут знать, что бывают массивы, а бываюи сваязанные списки

                                        В случае питона они не будут знать ничево, и не отличать объект от указателя
                                        Ответить
                                        • А в случае с PHP у них будет всего одна структура данных. И им будет её достаточно.

                                          Именно поэтому я за "РНР".
                                          Ответить
                                          • С PHP программистом потом уже ничего нельзя сделать.
                                            Только выкинуть, и нового родить
                                            Ответить
                            • Ну т.е. можно было не выёбываться с итераторами и их концептами, а сделать концепты для самих контейнеров, как в жабе. По крайней мере было бы сразу понятно, что для чего применять. А сами итераторы оставить как деталь реализации, которая нужна только разрабу новых контейнеров.
                              Ответить
                            • Пока крестовики будут подбирать правильную кобенацию из своих конь-тейнеров, скриптушки закодят всё на generic структурах данных и пойдут брать другой заказ.
                              Ответить
                              • Так точня. Поэтому за PHP будущее, а остальные языки, где нядо думать, сгниют!
                                Ответить
                            • Пока крестовики будут подбирать правильную кобенацию из своих конь-тейнеров, скриптушки закодят всё на generic структурах данных и пойдут брать другой заказ.
                              Ответить
                              • Так точня. Поэтому за PHP будущее, а остальные языки, где нядо думать, сгниют!
                                Ответить
                                • У меня нет в контроллерах никакого PHP, именно поэтому я за контроллеры. И std::kokokoнтейнеров из крестоговна тоже нет.
                                  Ответить
                                  • > У меня нет в контроллерах никакого PHP
                                    https://www.youtube.com/watch?v=ouUloBNBhOA

                                    > И std::kokoнтейнеров из крестоговна тоже нет.
                                    Тебе ня придётся учить стандартную библиотеку, если каждый раз ты пишешь стандартную библиотеку сам╰(▔∀▔)╯!
                                    Ответить
                                    • > Тебе ня придётся учить стандартную библиотеку, если каждый раз ты пишешь стандартную библиотеку сам

                                      Стандартная библиотека крестоговна мне там банально не подходит т.к. там требуется какой-то хип, а у меня в контроллерах может не быть никакого хипа (если всё решаемо статической памятью), а еще там какие-то исключения RTTI и прочая такая питушня, которая мне в контроллерах няхуй не нужна. Да и в целом можно поднасобрать каких-то реализаций различной питушни на сишечке с гитхаба, и ее использовать вместо крестовой говностдлибы.
                                      Ответить
                                    • > Тебе ня придётся учить стандартную библиотеку, если каждый раз ты пишешь стандартную библиотеку сам

                                      Стандартная библиотека крестоговна мне там банально не подходит т.к. там требуется какой-то хип, а у меня в контроллерах может не быть никакого хипа (если всё решаемо статической памятью), а еще там какие-то исключения RTTI и прочая такая питушня, которая мне в контроллерах няхуй не нужна. Да и в целом можно поднасобрать каких-то реализаций различной питушни на сишечке с гитхаба, и ее использовать вместо крестовой говностдлибы.
                                      Ответить
                                      • > там требуется какой-то хип
                                        Зачем?

                                        > исключения RTTI
                                        -fno-exceptions -fno-rtti

                                        > Да и в целом можно поднасобрать каких-то реализаций различной питушни на сишечке с гитхаба, и ее использовать вместо крестовой говностдлибы.
                                        И собрать свою говнолибу.
                                        Ответить
                                        • > > там требуется какой-то хип
                                          > Зачем?

                                          Память выделять там, например для какой-нибудь там std::list питушни. Без хипа я могу например так сделать: https://govnokod.ru/23275
                                          Ответить
                                        • > > там требуется какой-то хип
                                          > Зачем?

                                          Память выделять там, например для какой-нибудь там std::list питушни. Без хипа я могу например так сделать: https://govnokod.ru/23275
                                          Ответить
                                          • > так сделать

                                            Ну в бусте вроде были такие контейнеры... И интрузив списки, которые сишники любят делать руками тоже были.

                                            А стд, конечно, очень сильно завязано на хип и исключения. 90% стандартной либы можно тупо выбросить под фристендингом.
                                            Ответить
                                          • Так можня сделать свой собственный аллокатор. Там по сути просто обернуть всю эту алгоритмушню в одну структуру и всё.
                                            Ну а вообще в том посте roman-kashitsyn всё правильня расписал.
                                            Ответить
                                            • > сделать свой собственный аллокатор

                                              А как репортить ошибку, когда в нём место закончилось? Рушить абстракцию и приделывать аллокатору какое-нибудь has_enough_space()?
                                              Ответить
                                            • > Так можня сделать свой собственный аллокатор.

                                              А аллокатор может возвращать uint8_t ? Ну типа это память не вообще, а память, выделенная в контексте некоторой арены, где мы адресуемся не по байтикам, а по блокам в 16 байтиков, и этот возвращаемый uint8_t это смещение относительно какого-то там указателя в этой арене, который надо еще на 16 умножить и прибавить к этому базовому адресу чтоб получить реальный адрес
                                              Ответить
                                                • > указатель умещается в uint8_t

                                                  Не, он хочет что-то в духе кастомного std::vector::pointer. Чтобы там не настоящий поинтер был, а какой-то компактный тип, который можно через какую-то арифметику превратить в настоящий.

                                                  З.Ы. Ну кстати можно, походу. Этот тип из аллокатора берётся как раз. Если он будет вести себя как поинтер, то вектор схавает.
                                                  Ответить
                                                  • Хм, можня упороться ня отличненько: перегружаем new, чтобы принимал uint8_t, и унярный &, чтобы возвращал индекс элемента в каком-то статическом массиве.
                                                    Ответить
                                                • > указатель умещается в uint8_t

                                                  Не, он хочет что-то в духе кастомного std::vector::pointer. Чтобы там не настоящий поинтер был, а какой-то компактный тип, который можно через какую-то арифметику превратить в настоящий.

                                                  З.Ы. Ну кстати можно, походу. Этот тип из аллокатора берётся как раз. Если он будет вести себя как поинтер, то вектор схавает.
                                                  Ответить
                                                • > Если у тебя указатель умещается в uint8_t — может.

                                                  А если не уменьшается, и если я не хочу хранить полный указатель под каждую хрень? Есть один настоящий указатель, и куча смещений от него, и эти смещения влезают uint8_t без проблем.
                                                  Ответить
                                                  • > я не хочу хранить полный указатель под каждую хрень

                                                    Ну там в трейтах аллокатора можно указать свой тип для pointer. Может и прокатит что-то кастомное, если прикрутить звезду и скобочки.

                                                    Просто uint8_t нельзя, конечно. Но структурка или енум с uint8_t могут прокатить.
                                                    Ответить
                                                    • > Ну там в трейтах аллокатора можно указать свой тип для pointer. Может и прокатит что-то кастомное, если прикрутить звезду и скобочки.

                                                      Трейты-хуёйты, может и прокатит, а может не прокатит... Ясно всё.

                                                      Сколько надо будет с этим примерно ебаться, и много ли я от этого выиграю на своих задачах?
                                                      Ответить
                                                  • > я не хочу хранить полный указатель под каждую хрень

                                                    Ну там в трейтах аллокатора можно указать свой тип для pointer. Может и прокатит что-то кастомное, если прикрутить звезду и скобочки.

                                                    Просто uint8_t нельзя, конечно. Но структурка или енум с uint8_t могут прокатить.
                                                    Ответить
                                                  • А зачем аллокатору хранить указатель? Задача аллокатора — просто вернуть его, примерня как "return &static_arr[free_idx++]".

                                                    Кстати, std::list хранит ня указатели, а Allocator::pointer, так что можня попробовать упороться с таким аллокатором. Но лучше, конечно, использовать нярмальные intrusive list.
                                                    Ответить
                                                • > Если у тебя указатель умещается в uint8_t — может.

                                                  А если не уменьшается, и если я не хочу хранить полный указатель под каждую хрень? Есть один настоящий указатель, и куча смещений от него, и эти смещения влезают uint8_t без проблем.
                                                  Ответить
                                          • Так можня сделать свой собственный аллокатор. Там по сути просто обернуть всю эту алгоритмушню в одну структуру и всё.
                                            Ну а вообще в том посте roman-kashitsyn всё правильня расписал.
                                            Ответить
                                            • > сделать свой собственный аллокатор

                                              А как репортить ошибку, когда в нём место закончилось? Рушить абстракцию и приделывать аллокатору какое-нибудь has_enough_space()?
                                              Ответить
                                                • > exit (-1);

                                                  Ну заебись для эмбеддеда... На какую-нибудь опциональную хуйню для UI памяти не хватило, весь чип ушёл в ребут.
                                                  Ответить
                                                  • > Ну заебись для эмбеддеда...

                                                    Настоящие цари заранее должны знать, что им там всего хватит под все возможные сценарии. Если вдруг памяти не хватает, это баг, и надо менять структуру или допаивать ОЗУ или менять контроллер
                                                    Ответить
                                                  • > Ну заебись для эмбеддеда...

                                                    Настоящие цари заранее должны знать, что им там всего хватит под все возможные сценарии. Если вдруг памяти не хватает, это баг, и надо менять структуру или допаивать ОЗУ или менять контроллер
                                                    Ответить
                                                  • Ну так если в микроконтроллере место закончилось — это в любом случае всё, финита ля комедия.

                                                    > Железка может уметь много чего делать, и ей может быть не нужно делать это одновременно (и памяти на одновременное делание всего у нее тоже нет). Поэтому железка может выделять память под някню№1, сделать някню№1, освободить память, выделить память под някню№2, сделать някню№2, освободить память. И эти хуйни№x может быть много, некоторые не сильно жрущие оперативку хуйни могут вполне работать одновременно, и они могут быть заранее неизвестны т.е. загружаться с внешнего флеш-накопителя или по блютузу какому-то скачиваться и устанавливаться, если это какая-то IoT-няшнота. Так что для каких-то задач это вполне себе пригождается.
                                                    https://govnokod.ru/27391#comment625630
                                                    Ответить
                                                  • Ну так если в микроконтроллере место закончилось — это в любом случае всё, финита ля комедия.

                                                    > Железка может уметь много чего делать, и ей может быть не нужно делать это одновременно (и памяти на одновременное делание всего у нее тоже нет). Поэтому железка может выделять память под някню№1, сделать някню№1, освободить память, выделить память под някню№2, сделать някню№2, освободить память. И эти хуйни№x может быть много, некоторые не сильно жрущие оперативку хуйни могут вполне работать одновременно, и они могут быть заранее неизвестны т.е. загружаться с внешнего флеш-накопителя или по блютузу какому-то скачиваться и устанавливаться, если это какая-то IoT-няшнота. Так что для каких-то задач это вполне себе пригождается.
                                                    https://govnokod.ru/27391#comment625630
                                                    Ответить
                                                • > exit (-1);

                                                  Ну заебись для эмбеддеда... На какую-нибудь опциональную хуйню для UI памяти не хватило, весь чип ушёл в ребут.
                                                  Ответить
                                                  • > Ну заебись для эмбеддеда...

                                                    Настоящие цари заранее должны знать, что им там всего хватит под все возможные сценарии. Если вдруг памяти не хватает, это баг, и надо менять структуру или допаивать ОЗУ или менять контроллер
                                                    Ответить
                                                  • Ну так если в микроконтроллере место закончилось — это в любом случае всё, финита ля комедия.

                                                    > Железка может уметь много чего делать, и ей может быть не нужно делать это одновременно (и памяти на одновременное делание всего у нее тоже нет). Поэтому железка может выделять память под някню№1, сделать някню№1, освободить память, выделить память под някню№2, сделать някню№2, освободить память. И эти хуйни№x может быть много, некоторые не сильно жрущие оперативку хуйни могут вполне работать одновременно, и они могут быть заранее неизвестны т.е. загружаться с внешнего флеш-накопителя или по блютузу какому-то скачиваться и устанавливаться, если это какая-то IoT-няшнота. Так что для каких-то задач это вполне себе пригождается.
                                                    https://govnokod.ru/27391#comment625630
                                                    Ответить
                                            • > Так можня сделать свой собственный аллокатор.

                                              А аллокатор может возвращать uint8_t ? Ну типа это память не вообще, а память, выделенная в контексте некоторой арены, где мы адресуемся не по байтикам, а по блокам в 16 байтиков, и этот возвращаемый uint8_t это смещение относительно какого-то там указателя в этой арене, который надо еще на 16 умножить и прибавить к этому базовому адресу чтоб получить реальный адрес
                                              Ответить
                                                • > указатель умещается в uint8_t

                                                  Не, он хочет что-то в духе кастомного std::vector::pointer. Чтобы там не настоящий поинтер был, а какой-то компактный тип, который можно через какую-то арифметику превратить в настоящий.

                                                  З.Ы. Ну кстати можно, походу. Этот тип из аллокатора берётся как раз. Если он будет вести себя как поинтер, то вектор схавает.
                                                  Ответить
                                                  • Хм, можня упороться ня отличненько: перегружаем new, чтобы принимал uint8_t, и унярный &, чтобы возвращал индекс элемента в каком-то статическом массиве.
                                                    Ответить
                                                  • Хм, можня упороться ня отличненько: перегружаем new, чтобы принимал uint8_t, и унярный &, чтобы возвращал индекс элемента в каком-то статическом массиве.
                                                    Ответить
                                                • > Если у тебя указатель умещается в uint8_t — может.

                                                  А если не уменьшается, и если я не хочу хранить полный указатель под каждую хрень? Есть один настоящий указатель, и куча смещений от него, и эти смещения влезают uint8_t без проблем.
                                                  Ответить
                                                  • > я не хочу хранить полный указатель под каждую хрень

                                                    Ну там в трейтах аллокатора можно указать свой тип для pointer. Может и прокатит что-то кастомное, если прикрутить звезду и скобочки.

                                                    Просто uint8_t нельзя, конечно. Но структурка или енум с uint8_t могут прокатить.
                                                    Ответить
                                                    • > Ну там в трейтах аллокатора можно указать свой тип для pointer. Может и прокатит что-то кастомное, если прикрутить звезду и скобочки.

                                                      Трейты-хуёйты, может и прокатит, а может не прокатит... Ясно всё.

                                                      Сколько надо будет с этим примерно ебаться, и много ли я от этого выиграю на своих задачах?
                                                      Ответить
                                                      • > Сколько надо будет с этим примерно ебаться

                                                        Х.з., я тут только пессимистичный прогноз могу дать. Наебавшись с boost intrusive списком я тупо выбросила его нахуй и написала свой за 5 минут.
                                                        Ответить
                                                    • > Ну там в трейтах аллокатора можно указать свой тип для pointer. Может и прокатит что-то кастомное, если прикрутить звезду и скобочки.

                                                      Трейты-хуёйты, может и прокатит, а может не прокатит... Ясно всё.

                                                      Сколько надо будет с этим примерно ебаться, и много ли я от этого выиграю на своих задачах?
                                                      Ответить
                                                      • > Сколько надо будет с этим примерно ебаться

                                                        Х.з., я тут только пессимистичный прогноз могу дать. Наебавшись с тем же boost intrusive списком, я тупо выбросила его няхуй и написала свой за 5 минут.
                                                        Ответить
                                                      • > Сколько надо будет с этим примерно ебаться

                                                        Х.з., я тут только пессимистичный прогноз могу дать. Наебавшись с тем же boost intrusive списком, я тупо выбросила его няхуй и написала свой за 5 минут.
                                                        Ответить
                                                  • А зачем аллокатору хранить указатель? Задача аллокатора — просто вернуть его, примерня как "return &static_arr[free_idx++]".

                                                    Кстати, std::list хранит ня указатели, а Allocator::pointer, так что можня попробовать упороться с таким аллокатором. Но лучше, конечно, использовать нярмальные intrusive list.
                                                    Ответить
                                                    • > зачем аллокатору хранить указатель

                                                      Списку, который на основе этого аллокатора работает, нужны указатели. Ну и тратить на них по 4 байта не хотелось бы, если список маленький.

                                                      > нярмальные intrusive list

                                                      Их, кстати, довольно сложно юзать в режиме "несколько списков через одни и те же объекты"... При том, что внутри там ерунда по переключению линков, которая пишется буквально за 5 минут (и в ней даже условий нет, так что юнит-тест элементарен). Ну в данной конкретной задаче может быть и прокатят.
                                                      Ответить
                                                    • intrusive это когда внутри объекта есть ссылки на тудой и сюдой?
                                                      Ответить
                                                      • > внутри объекта есть ссылки на тудой и сюдой

                                                        Да, ссылки ты размещаешь в объекте сам и поясняешь либе как ими пользоваться.
                                                        Ответить
                                                        • И экономишь этим лишние обращения?

                                                          Так-то ты мог свой итератор со своим ++ написать и в 03 еще
                                                          Ответить
                                                          • > экономишь этим лишние обращения

                                                            Скорее оставляешь управление памятью за собой, как в сишке. А "контейнер" даёт тебе attach/detatch вместо insert/remove.

                                                            В теории могло бы быть полезно, когда тебе надо 2-3 списка построить через одни и те же ноды. Но на практике мне не удалось запинать эти злоебучие трейты, пришлось решать эту задачу руками.
                                                            Ответить
                                                          • > экономишь этим лишние обращения

                                                            Скорее оставляешь управление памятью за собой, как в сишке. А "контейнер" даёт тебе attach/detatch вместо insert/remove.

                                                            В теории могло бы быть полезно, когда тебе надо 2-3 списка построить через одни и те же ноды. Но на практике мне не удалось запинать эти злоебучие трейты, пришлось решать эту задачу руками.
                                                            Ответить
                                                            • а, понял идею

                                                              Делаешь один связанный список, и по нему строишь два других списска: один напрямую, другой через один, например?
                                                              Ответить
                                                            • а, понял идею

                                                              Делаешь один связанный список, и по нему строишь два других списска: один напрямую, другой через один, например?
                                                              Ответить
                                                              • Ну тип того. Список проснувшихся тредов и список тредов в процессе, к примеру.

                                                                Это всё решается и на обычных контейнерах, конечно. Но по памяти/пирфомансу будет совсем не айс.
                                                                Ответить
                                                                • А чем плохо вручную покласть их в кучу, а в контейнеры покласть на них ссылки/указатели?

                                                                  Тем, что придется обёртку делать на каждый такой указатель?
                                                                  Ответить
                                                                  • > вручную покласть их в кучу, а в контейнеры покласть на них ссылки/указатели

                                                                    Ну получается слишком много мелкой хуйни и аллокаций для неё. Если у тебя какие-нибудь треды тыщи раз в секунду просыпаются и засыпают, как-то стрёмно аллокатор дрочить каждый раз. Особенно если в этих местах аллокатор вообще трогать нельзя.

                                                                    А с интрузивом оно интегрировано в основную структуру. Ну как сишник бы сделал.
                                                                    Ответить
                                                                    • А, понятно: в intrusive я могу кучу вообще не трогать например (ну во всяком случае не аллочить ничего) и просто класть структуру, в указателе "next" которой будет именно нужное мне значение?
                                                                      Ответить
                                                                    • А, понятно: в intrusive я могу кучу вообще не трогать например (ну во всяком случае не аллочить ничего) и просто класть структуру, в указателе "next" которой будет именно нужное мне значение?
                                                                      Ответить
                                                                      • Ну да, в системном сишном коде этот паттерн очень часто встречается. Когда у тебя посреди большой структуры лежат какие-нибудь next/prev или left/right/parent от всяких разных "контейнеров", в которые она входит.

                                                                        А в самих "контейнерах", по сути, только башка этих списков/деревьев.
                                                                        Ответить
                                                                        • ну в общем intrusive это такой сахарок, чтобы вручную не разыменовывать указатели, а ходить по "виртуальным" контейнерам (небось еще итераторами и небось их можно сувать даже в стандартные алгоритмы)
                                                                          Ответить
                                                                          • Ну как-то так, да. Есть ещё intrusive аналог shared'а, в котором у тебя счётчик вшит в сам объект чтобы отдельный управляющий блок не городить. Ну или если у тебя счётчик уже есть (COM объект какой-нибудь).
                                                                            Ответить
                                                                            • забавно, я думал как-то как подружить Com c шариком, в итоге взял CComObject из ATL, он примерно это и делает
                                                                              Ответить
                                                                            • > intrusive аналог shared'а

                                                                              Спасибо, ты прям вернул говнокод 2010-го.
                                                                              Ответить
                                                                            • > intrusive аналог shared'а
                                                                              В крестах, кстати, есть std::make_shared(). По Стандарту std::make_shared() обязана делать только одну аллокацию, сшивая управляющий блок с данными. Так что shared_ptr, сделанный через make_shared(), и shared_ptr, сделанный через конструктор — две очень большие разницы.
                                                                              Ответить
                                                                              • уж не хочеш ли ты сказать, что интрузив не умела emplace?
                                                                                Ответить
                                                                                  • >Если при этом в foo() возникнет исключение — получаем утечку экземпляра Bar.

                                                                                    блядь, какой С++ сложный

                                                                                    шарик помрет, потому что померло всё выражение, а Bar никто не делитнул, вот он и остался, верно?

                                                                                    шарик тут суть вообще временный обхект же
                                                                                    Ответить
                                                                                    • В том примере снячала выделяется память через new Bar, потом вызывается foo(), из няго вылетает исключение, и до конструктора std::shared_ptr указатель из new Bar просто ня доходит.
                                                                                      Во всяком случае, так было раньше, а теперь уже всё отличня.
                                                                                      > Начиная с c++17 утечка памяти в том хитром редком примере, ради которого в STL был добавлен std::make_shared, уже невозможна.
                                                                                      Ответить
                                                                              • Было смешно смотреть на "оптимизацию", где на большой ресурс, аллоцированный make_shared, сохраняли слабый указатель. По замыслу, если ресурс не нужен, то он разрушится и освободит память, а потом, если weak_ptr протухший, его можно заного загрузить.

                                                                                Проблема в том что этот ресурс — по сути дела struct { char[8294400] }.
                                                                                Ответить
                                                                              • Было смешно смотреть на "оптимизацию", где на большой ресурс, аллоцированный make_shared, сохраняли слабый указатель. По замыслу, если ресурс не нужен, то он разрушится и освободит память, а потом, если weak_ptr протухший, его можно заного загрузить.

                                                                                Проблема в том что этот ресурс — по сути дела struct { char[8294400] }.
                                                                                Ответить
                                                                                • > то он разрушится и освободит память
                                                                                  > make_shared
                                                                                  Какой эпичный выстрел в ногу!
                                                                                  Ответить
                                              • ну двайте уже, изобретите сегментную адресацию

                                                а потом дальние и ближние указатели
                                                Ответить
                                        • > И собрать свою говнолибу.

                                          Которая не будет всякую ненужную питушню треботвать, и будет эффективна по потреблению памяти.
                                          Ответить
                                        • > И собрать свою говнолибу.

                                          Которая не будет всякую ненужную питушню треботвать, и будет эффективна по потреблению памяти.
                                          Ответить
                                    • >Тебе ня придётся учить стандартную библиотеку, если каждый
                                      > раз ты пишешь стандартную библиотеку сам

                                      "В Go распространен подход к выполнению большенства рутинных задач явно, уменьшая сложность понимания кода"

                                      буду теперь форсить эту фразу везде
                                      Ответить
  • меня "begin()" & "end()" вседа выбешивали в С++. Не ужто так было струдно нормальный интератор заиплементировать.
    Ответить
    • > нормальный интератор

      Что понимается под "нормальным"? Убожество как в джаве, дотнете или скриптушне, которое только для последовательного обхода пригодно?

      Всё-таки крестовые итераторы пытались решить большую задачу, чем просто обход контейнера по порядку.
      Ответить
      • > Всё-таки крестовые итераторы пытались решить большую задачу

        Пытались )))

        А какой должен быть нормальный итератор? Какую глобальную проблему решили итераторы в крестах, которую в скриптушне решить не смогли? Допустим, в питоне.
        Ответить
        • > Какую глобальную проблему решили итераторы в крестах

          Указать на слайс контейнера чтобы удалить его или заменить на что-то другое, к примеру. Или (осторожно) удалять элементы из контейнера прям во время его обхода. Или найти элемент в мапе и записать в него новое значение не делая повторный поиск. Или даже проделать над ними какую-то арифметику(!), если random access.

          В питоне, емнип, имея итератор ты вообще ничего не можешь сделать. Ну кроме как достать из него следующее значение.
          Ответить
          • В Питоне для этого несколько другие вещи используются. Но в 1998 году альтернатив особо не было.

            Итераторы в крестах предназначались, как точка кастомизации. Захотел сделать итератор, который проходит по вектору строк и выдаёт только слова, имеющиеся в словаре, приведённые к нижнему регистру. Или проходит сначала по нечётным, а потом по чётным индексам — сделал, передал в имеющуюся функцию и всё работает.
            Ответить
            • > проходит по вектору строк и выдаёт

              Ну просто для обхода хватило бы и убогого forward iterator'а, которым хвалятся джавы да питоны.

              Хотя... их итератор даже на forward не тянет т.к. его нельзя передать в какой-нибудь erase() или заюзать как границу для последующего поиска.
              Ответить
                • А джаве они вроде говорят что "всё" спец методом
                  Но это не важно.

                  Важно, что они итераторы своего конца никогда не знают, и потому всякие крутые штуки как в крестах с ними не сделать
                  Ответить
              • вы знаете что такое принцим immutable object и зачем это надо?
                Ответить
              • вы знаете что такое принцим immutable object и зачем это надо?
                Ответить
              • вы знаете что такое принцим immutable object и зачем это надо?
                Ответить
          • > Указать на слайс контейнера чтобы удалить его или заменить на что-то другое

            Такое есть в скрипушне, а ещё в «Nim», кажется.

            > Или (осторожно) удалять элементы из контейнера прям во время его обхода.

            Такого, кажется, в скриптушне действительно нет. Раньше же итератор протухал как только его коллекцию как-либо меняли? Тогда крутая фича.

            Хотя нет, в питоне можно вот так:
            array = [1, 2, 3, 4, 5]
            for e in array:
                if e % 2 == 0:
                    array.remove(e)
            print (array) # [1, 3, 5]

            Это ведь итератор работает!

            > В питоне, емнип, имея итератор ты вообще ничего не можешь

            Это правда лишь отчасти. В питоне есть слайсы, генераторы и итераторы, которые делают всякие приколы. Я правильно понял, что «Ranges» просто совместил в себе все эти финтифлюшки? Справедливо ли утверждение, что крестобляди соснули, т.к. им пришлось комюпировать функционал из скриптушни? Или это скриптобляди поспешили и людей насмешили, а крестобояре обстоятельно подумали и сделали как надо?
            Ответить
            • Генератор/итератор в Питоне это, вроде как InputRange/ForwardRange в крестах (Не помню, копирование итераторов там починили или нет). Фактически это чаще всего используемая конструкция, но иногда хочется и к предыдущему элементу вернуться, и копию итератора сохранить. Передать итератор и построить кучу из последовательности, на которую он ссылается ЕМНИП в Питоне не получится.
              Ответить
            • Генератор/итератор в Питоне это, вроде как InputRange/ForwardRange в крестах (Не помню, копирование итераторов там починили или нет). Фактически это чаще всего используемая конструкция, но иногда хочется и к предыдущему элементу вернуться, и копию итератора сохранить. Передать итератор и построить кучу из последовательности, на которую он ссылается ЕМНИП в Питоне не получится.
              Ответить
            • > array.remove(e)
              Это удаление элемента по знячению. Об эффективнясти такого можня догадаться.
              Ответить
            • > array.remove(e)
              Это удаление элемента по знячению. Об эффективнясти такого можня догадаться.
              Ответить
              • Для скриптуха это вполне допустимо

                По идее нужно найти элемент за O(N) (если нет требования сортированности массива) и, удалив элемент, двигануть пол массива. Какой окшмар
                Ответить
              • Для скриптуха это вполне допустимо

                По идее нужно найти элемент за O(N) (если нет требования сортированности массива) и, удалив элемент, двигануть пол массива. Какой окшмар
                Ответить
                • А потом повторить для всех попавших под условие элементов. Один цикл — O(N^3), какое ня!
                  Ответить
                  • а он удаляет все или толкьо первый?

                    если все, то логично сначала все найти, потом подвигать.

                    А нельзя явно заказать линкдлист вместо массива, если уж мы такие удалятели знатные?
                    Ответить
                    • Только первый.

                      > А нельзя явно заказать линкдлист вместо массива, если уж мы такие удалятели знатные?
                      Нят. Это слишком сложня для скриптов.
                      Ответить
                      • Ну да, не стоит засирать мозг лишними типами данных

                        Именно потому я за перл: массив, хеш, да скляр. Всё
                        Ответить
                          • Ну кстати да.
                            Берешь, и делаешь нужную структуру под конкретную задачу

                            Потому мне всегда смешно от сёмных нахрюков про "в си даже мапы нету"

                            вон сколько сложностей возникло в крестах из за STL контейнеров
                            Ответить
                            • > в си даже мапы нету

                              А в позиксе есть! Правда она одна на весь процесс и удалять из неё нельзя. Но это мелочи.
                              Ответить
                              • да, ее надо целиком грохать

                                там вроде и массив есть с байнари сёрчем... такие костыли, конечно
                                Ответить
                                  • хуясе, bsearch часть сишки, а я думал чото, что позикса:-/
                                    Ответить
                                      • lsearch юникс
                                        bsearch сишка
                                        tsearch юникс
                                        qsort сишка

                                        ужасный раздрай) Правда, по заголовочному фалйу понятно


                                        А в Win32 есть какинито алгоритмы интересные?
                                        Или у MS позиция "юзайте STL, пишите на крестах"?
                                        Ответить
          • вы милок, попутали курсоры с итераторами. задача итератора это перебор елементов - не более того.
            Ответить
            • Ну можешь считать, что это курсоры, раз так больше нравится.
              Ответить
            • Ну можешь считать, что это курсоры, раз так больше нравится.
              Ответить
          • вы милок, попутали курсоры с итераторами. задача итератора это перебор елементов - не более того.
            Ответить
            • Ну можешь считать, что это курсоры, раз так больше нравится.
              Ответить
            • В C++ это, разумеется, ня так.
              auto map = std::map<std::string, std::string, std::less<>>{{"hello", "world"}, {"bye", "sun"}};
              auto iterator = map.find("bye");
              if (iterator != map.end()) {
                  map.erase(iterator);
              }
              Ответить
              • Увеличиваем степень наркомании:
                CountingIterator<TransformIterator<StrideIterator<std::vector<int>::iterator>>> it {5, { squared, {3, cont.begin()}}};
                Ответить
              • Увеличиваем степень наркомании:
                CountingIterator<TransformIterator<StrideIterator<std::vector<int>::iterator>>> it {5, { squared, {3, cont.begin()}}};
                Ответить
            • Что такое "курсор"? Что-то из СУБД?

              В С++ есть несколько категорий итераторов:
              https://www.geeksforgeeks.org/introduction-iterators-c/

              Самые тупые их них могут только выдавать значение (разыменовываться) или только двигаться вперед (++)

              Самые продвинутые умеют даже random access.
              Некоторые умеют писать или удалять данные

              Все зависит от категории.
              Ответить
              • Он на Википедии про курсоры прочитал. Я тоже оттуда брал нахрюки!
                Ответить
              • "задача итератора это дать универсальный интерфейс перебора(доступа) для разных имлементаций коллекторов. на этом ее задачи кончены". Изменение коллекций в обязанности итераторов не входит а наоборот они должны обеспечить сохранность данных без изменений
                Ответить
                • То есть по твоему определению:
                  * Доступа к возвращаемому значению генераторов посредством итераторов не сделать (ведь это, о боже, изменит значение генератора)
                  * Ленивых итераторов быть не может (ведь доступ к значению заставит это значение изменится, какой ужас)
                  * Абстрагировать поток как коллекцию значений с помощью итератора не получится (поток меняется от чересчур пристального взгляда на него, кошмар).

                  И нахуя нужны такие итераторы?
                  Ответить
          • задача итератора это дать универсальный интерфейс перебора для разных имлементаций коллекторов. на это ее задачи кончены
            Ответить
          • задача итератора это дать универсальный интерфейс перебора для разных имлементаций коллекторов. на это ее задачи кончены
            Ответить
          • задача итератора это дать универсальный интерфейс перебора для разных имлементаций коллекторов. на это ее задачи кончены
            Ответить
        • легкий в имплементации и применении, интуитивный в использовании
          Ответить
        • легкий в имплементации и применении, интуитивный в использовании
          Ответить
  • "Welcome, please take your seats. Today's lecture is about Lazy Evaluation. The lecture is over, thank you for listening. Questions?"
    Ответить
  • "Welcome, please take your seats. Today's lecture is about Lazy Evaluation. The lecture is over, thank you for listening. Questions?"
    Ответить

Добавить комментарий

Где здесь C++, guest?!

    А не использовать ли нам bbcode?


    8