1. C++ / Говнокод #12483

    +22

    1. 1
    2. 2
    3. 3
    4. 4
    list<int> list;
    ...
    for(auto i=0;i<list.size();i++){
        auto item = *next(list.begin(), i);

    Вчера у меня появился каллега.
    http://liveworkspace.org/code/1AWg24$5
    Кажется я знаю, кто следующий будет сидеть на табуретке. Думаете стоит сказать ему?

    Запостил: LispGovno, 27 Января 2013

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

    • В нашем отделе ни одного сидящего на табуретке. Так что пока вопросов у него не возникает. Думаю пока он видел лишь доску позора, ну а на словах у нас обсуждать эту правильную методику почему-то не принято.
      Ответить
      • почему тебе понадобилось 6 итераций?
        соскучился по табуретке?
        и да, вчера была суббота
        Ответить
    • я у нас нечто подобное с LinkedList (вместо ArrayList) в жабном модуле как-то раз откопал. там вот так бегали по списку в ~10К элементов. спросил тестеров - не, на производительность никто не жаловался...

      > Кажется я знаю, кто следующий будет сидеть на табуретке.

      лучше посадить в камеру-одиночку без окон - и выдать страуструпа как единственное развлечение.
      Ответить
      • ты что, они же потом сразу свалят в какой-нибудь гугл
        Ответить
        • В гугл - только при дополнении книг Кнутом. А так - максимум в микрософт.
          Ответить
    • В крестах не силен, поэтому вопрос.
      Поясните в чем суть, в том что не используется итератор ?
      Ответить
      • > не используется итератор
        Используется, но через анус: *next(list.begin(), i). Дело в том, что крестовый list это именно список а не массив. Соответственно обращение к элементу по индексу - O(n), а весь алгоритм в целом - тормозное квадратичное говно с O(n^2).

        P.S. А еще тут list.size() вызывается на каждой итерации цикла. Хорошо, что list его все-таки хранит, а не считает каждый раз.
        Ответить
        • Гы гы O(n^3):
          forward_list<int> list;
          но не думаю, что автор о нем знает и слава богу
          Ответить
          • Хм, а откуда куб вылез? Один цикл точно также будет по i, второй внутри некста, а где третий?
            Ответить
            • forward_list<T>::size проходится по коллекции на каждой итерации цикла, чтобы посчитать размер
              Ответить
              • И таки откуда взялся куб?
                Ответить
                • Теже O(n^2), только больше. Затупил
                  Ответить
                  • Ой светит мне табуретка...
                    Ответить
                    • @bormand нашел в подсобке облезлый деревянный стул. Пригодится для внедрения прогрессивных методологий разработки.
                      Ответить
                      • Всё новое - это хорошо забытое старое. Не забудь вбить в него пару гвоздей.
                        http://tinyurl.com/aohd4w7
                        Ответить
                        • >Не забудь вбить в него пару гвоздей.
                          Тогда новичок сразу в Кармака превратится. Тоже будет стоя программы писать.
                          Ответить
                          • Кажется я теперь знаю как становятся Кармаками
                            Ответить
                            • Начнешь писать быдлокод?
                              Ответить
                              • А Кармак когда-нибудь писал быдлокод? Имхо он пишет хоть и на чистой сишке, но очень красиво.
                                Ответить
                                • Просматривал как-то ради интереса публично доступные сорцы кваки, ничего особо красивого там не увидел. Да и с третьей кваки как раз Кармак на плюсы переехал.
                                  Ответить
                                  • Справедливости ради именно после третьей кваки игры id скатились в говно.
                                    Но самое лютое это d2/q1 (еще тот интерфейс где внизу потрёпаная рожа героя). Тогда у них еще Ромеро дизайнером был.
                                    Ответить
    • Кстати, подобный код где-то видел у новичков много раз, но почему то раньше не обращал внимания, пока не начнутся крики от конечного пользователя о тормозах.
      Ответить
      • наши новички и особо задвинутые до такого еще не доходили. потому что STL пытается это сделать сложным.

        у нас более распространена практика использования list::size() вместо list::empty(). тоже весело.
        Ответить
        • и что, чем то серьезно отличается проверка size_t от проверки bool?
          Ответить
          • Ты не поверишь. В std::forward_list на порядок
            Ответить
            • ты не поверишь, но в std::forward_list такого метода даже нет
              http://en.cppreference.com/w/cpp/container/forward_list
              Ответить
              • Хе хе. А он был. Видимо в последний момент поправили перед выпуском.
                Ответить
                • @defecate-plusplus сам его убрал, поэтому знает.
                  Ответить
                  • Ну он же неспроста в прошлом году писал "в моем драфте с++".

                    P.S. Ну и сегодня "мой стандарт c++03 говорит".
                    Ответить
                    • в прошлом году, говорите... это уже какой-то новый драфт видимо
                      Ответить
                  • Да, юзернейм заиграл новыми красками
                    Ответить
                    • АХАХА бля угар точняк лол
                      Ответить
                      • Что смешного? Поясните мысль.
                        Ответить
                        • Ник его насрал-в-кресты выбран не случайно. Он действительно сделал это со стандартом оных.
                          Ответить
                          • Или "высираю кресты".
                            Ответить
                            • Петарасян в треде!
                              Ответить
                            • Это может быть неприятно и являться симптомом опасных заболеваний.
                              Ответить
                            • Это же так больно! А я цветочками какаю
                              Ответить
                              • > Это же так больно!
                                А кто сказал, что крестоблядство должно быть легким и приятным?
                                Ответить
                              • >Это же так больно
                                При правильной форме отверстия - нет
                                Ответить
                                • Порванное, чтобы крест выходил любой строной? А если крест германский?
                                  Ответить
                                • Как раз при правильной кресты будут выходить с трудом, цепляясь за стенки.
                                  Наверное, у крестоблядей кресты давно порвали жопу на 4 части и поэтому у них допа такой формы стала
                                  Ответить
                                  • >у них допа такой формы
                                    >у них допа
                                    >допа
                                    Чего?

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

                                    @LispGovno
                                    +1
                                    Ответить
                                    • Не, я не крестоблядь, я даже продолжаю троллить крестовиков, правда, я тонко их троллю?
                                      Ответить
                                      • >"я не крестоблядь".
                                        Классика. Сейчас у тебя переходный период с первой стадии - отрицания на вторую - гнев, злость и буйный протест.

                                        Запомни Тарас: признание - первый шаг к излечению.
                                        Ответить
          • std::list есть типичный связный список и не кэширует количество элементов.

            std::list::size() на каждый вызов пробегает список и считает количество элементов.
            Ответить
            • http://en.cppreference.com/w/cpp/container/list/size
              > Complexity
              > Constant or linear (until C++11)
              > Constant (since C++11)
              Ответить
              • на самом деле на or linear мой стандарт c++03 говорит однозначно:
                23.1 Container requirements
                Table 65—Container requirements (continued)
                a.size() complexity: (Note A)
                Those entries marked ‘‘(Note A)’’ should have constant complexity.
                Ответить
                • Предлагаю прочитать ещё раз.
                  >Those entries marked ‘‘(Note A)’’ should have constant complexity.
                  Рекомендация, но не более. Может быть хоть O(n^2), хотя это сделать сложно
                  Ответить
            • и минус то за что?
              Ответить
              • минус не мой. я минусую только матерщину.

                и минус совсем не правильный, т.к. если предположить что ты родился только вчера и знаешь только С++11, то ты не знаешь что в С++98 std::list::size() имел линейную производительность. :)
                Ответить
                • да сколько можно
                  открой уже стандарт с++98, да приведи пруф
                  делов то

                  вот ссылка на ISO/IEC 14882:2003, которая вроде как соответствует моей локальной версии
                  http://e-maxx.ru/bookz/files/cpp_standard.pdf
                  Ответить
                  • да и в с++98 текст аналогичный
                    ISO/IEC 14882:1998(E)
                    http://sites.cs.queensu.ca/gradresources/stuff/cpp98.pdf
                    Those entries marked ‘‘(Note A)’’ should have constant complexity.

                    линейные красноглазые пессимизации (см ниже) требуют дополнительного расследования
                    Ответить
                    • Note A says:
                      Those entries marked ‘‘(Note A)’’ should have constant complexity.
                      However, that does not mean that those entries shall have constant complexity. Standards use very specific terminology, and "should" means it's not required.

                      судя по интернетам, гццшники дотянули O(n) в std::list::size вплоть до 4.8
                      в отличие от msvc и libc++

                      и вот еще интересная статейка
                      http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2923.pdf
                      Ответить
                    • stlports 3.x & 4.x - точно O(n). GCC'шная STL (только что глянул) тоже обычный линкед лист и тоже не кэширует размера.

                      итератор тоже не поддерживает арифметики за исключение инкремента и декремента (в отличии например от векторного итератора). (поэтому то в листе никогда и operator[] не был реализован.)

                      "(Note A)" сам нашел в стандарте. может я отстал от времени, но как можно сделать подсчет елементов в О(1) я не в курсе.
                      Ответить
                      • > как можно сделать подсчет елементов в О(1) я не в курсе.
                        Ты не поверишь, но инкрементировать переменную при добавлении или удалении декрементировать при удалении элементов в листе.
                        Ответить
                        • в класической реализации списка, нету просто места куда эту переменную воткнуть: объект списка == элемент списка.

                          как по мне, нету тут проблемы. если мне нужно знать количество элементов, я пользуюсь вектором, если надо вставлять в середине - то листом.
                          Ответить
                          • > в класической реализации списка
                            Как это некуда? А сам объект класса std::list? Он то явно не является первым элементом списка, а просто содержит указатель на оный. Вот в него и можно запихать.
                            Ответить
                            • А, понял. Под классической подразумевается ужасная реализация, в которой нет обертки над головой списка, и в функции вставки\поиска приходится передавать указатель на указатель на голову:
                              struct list_node {
                                  int value;
                                  struct list_node *next;
                              };
                              
                              void prepend(struct list_node **list, struct list_node *new_node) {
                                  new_node->next = *list;
                                  *list = new_node;
                              }
                              
                              struct list_node *list = NULL;
                              prepend(&list, node1);
                              prepend(&list, node2);
                              Ответить
                              • > А, понял. Под классической подразумевается ужасная реализация, в которой нет обертки над головой списка, и в функции вставки\поиска приходится передавать указатель на указатель на голову

                                Это называется интрузивный (Хотя по моему в бусте этому выражению давали какоето другое значение) список. Более того почти такой же, как описан выше бормандом, только имеющий простейшую обертку, чтобы не торчал голый указатель - это std::forward_list, который кто-то предполагал для lock_free работы и поэтому тот не считает число элементов в себе, а зря, так как для локфри он не годится ни каким боком, если только не вставлять меморибарьеры вручную (не попали они в стандарт же? поэтому не годится ни в каком виде) (мне чего-то кажется что с моделью памяти С++ вообще барьеры даже не помогут).

                                В std::list это лишняя пессимизация, так как для локфри он тем более не годится (так как двухнаправленный) и там по любому нужны локи.
                                Ответить
                                • А вообще С++ вступает в новую многопоточную среду, а контейнеры и алгоритмы мало того что не пригодны для автопараллелизации и векторизации, так ещё нет локфри и синхронизированных локами контейнеров в стандартной библиотеке. Вообщем мне кажется создатели крестов так смеются над нами. Жабаватели и сишарписты могут легко выкатывать новый стандарт с поддержкой многопоточности или множества новых фич, в то время как создатели/стандартизаторы крестов в течении нескольких лет жрут свой кактус, а выкатывают три каллечных алгоритма, нисколько не приблизившись к сути и нисколько не догнав по функционалу ни один вменяемый язык. Что-то они делают не так. Может насилуют труп?
                                  Ответить
                                  • не принимая во внимание микрософто-интеловскую работу над concurrent_*/tbb, в бусте же тоже что-то там ворочались над lockfree:
                                    http://lists.boost.org/boost-announce/2011/08/0331.php
                                    типа ACCEPTED, но в списке библиотек не наблюдаю

                                    ага, вот кое-что
                                    http://www.boost.org/development/tests/release/developer/lockfree.html
                                    может в ближайшей версии будет
                                    Ответить
                                    • > Unexpected success; follow the link for more details.
                                      Улыбнуло в тестах.

                                      Вижу очередь, вижу стек, вижу лист, вижу hazard_pointer (tagget_ptr). Это конечно минимально необходимо, но не все что нужно для многопоточных библиотек (нужные ещё деревья, мапы, графы и тд). Это только минимальная поддержка локфрии.
                                      Локфри болталось уже много времени непринятым в бусте, но его не принимали, так как он не соответствует интерфейсу стандартных контейнеров (на крестах приниматели похоже просрали последние мозги, я это подругому понять не могу). Неужели так трудно понять, что интерфейс стандартной библиотеки не подходит ни под локфри, ни под многопоточность. Не возможно провести такую унификацию. Изначально просто контейнеры под это не проектировались и вообще библиотека не проектировалась и потому интерфейсы в ней не подходят. А вот мне интересно какого хрена в бусте делает hazard_pointer? Он блин запатентован. Кто платить бабки будет? Неужели пользователи буста?
                                      Ответить
                                      • > он не соответствует интерфейсу стандартных контейнеров
                                        Что ты, безпринципное гумно, можешь знать о любви сынов страуструпа к stl-контейнерам?!
                                        http://sourceforge.net/apps/trac/stldb/
                                        Ответить
                                        • Хороший вброс. Плюсанул.
                                          Ответить
                                          • Кстати жду наброса от дификатного брата страуса.
                                            Ответить
                                            • какого наброса ты ждешь? вот недавно делал говнорефлексию "структур" на крестах с нулевым оверхедом
                                              Ответить
                                              • > делал говнорефлексию "структур" на крестах с нулевым оверхедом
                                                /me жаждет деталей
                                                Ответить
                                                • решалась проблема:
                                                  есть структура, в которой живут целочисленные поля, и реже вперемешку с массивами/строками

                                                  целочисленное поле занимает свое число бит, обычно не кратное 8
                                                  соответственно, поля друг за другом тесно упакованы, т.е. если первое поле - 14 бит, второе - 6, а третье - 30, то третье начинается по смещению 20 и занимает ровно 30 бит

                                                  для этого в языке, в принципе, есть битовые поля, однако в них есть существенный непреодолимый недостаток - битовое поле не может пересекать некую границу "слова" (unsigned long, например) и маленький недостаток - на big/little endian начинаются кручу-верчу-запутать хочу в декларации

                                                  каждое поле имеет некую семантику, которая отличает его от любого другого,
                                                  всего несколько десятков этих "семантик"

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

                                                  каждый формат отличается от другого тем, что может иметь, а может не иметь конкретное сематическое поле, и конкретное семантическое поле имеет разную длину в разных форматах (длину, но не тип)
                                                  в одном формате не будет двух сематически одинаковых полей

                                                  все форматы надо примерно одинаковым образом обрабатывать, с нюансами, есть ли в нем специфичные поля (поддерживает ли он некую специфичную логику над этими полями)
                                                  Ответить
                                                  • в общем сделал, что 1) описание конкретного формата максимально удобно для меня (нет ебанутого геморроя с ручным подсчетом смещения каждого поля, есть только список полей с указанием их длины), 2) get и set любого поля имеет минимальный ассемблер (там в компайл-тайм получаются все офсеты и длины, поэтому качество чтения и записи равно родным битовым полям), 3) в компайл-тайм можно выяснить есть в конкретном формате поле или нет (не то, чтобы полезно), и более полезно, от формата можно запросить любое поле и вызвать у него bool exists() (компайл-тайм сложность), что позволяет на крестах писать нормальный эффективный код обработки в отсутствие static_if, 4) форматы присваиваются друг другу, сравниваются/сортируются по конкретным полям, помеченным у них как индексные, 5) поддержка big и little endian, 6) весь объект, хранящий конкретный формат и способный в каждое свое поле читать и писать, имеет sizeof = 1*sizeof(void *) - хранит один указатель на область памяти, где этот формат наложен,
                                                    как бонусы - 7) формат самостоятельно выведет свое содержимое в ostream в виде "имя поля" - значение, поэтому 8) при желании можно сделать в него запрос в рантайме "найди мне ссылку на поле с таким именем" (ср. с компайл-таймом - "найди мне ссылку на поле с такой семантикой") - пока не пригодилось, пригодится в автотестах

                                                    целочисленные поля имитируют тип {ushort, ulong, ulonglong} в операциях чтения/записи, массивы - boost::array, строки - std::string

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

                                                    вот такая говнорефлексия
                                                    Ответить
                                                    • А можно взглянуть одним глазком на то, как примерно это реализовано мастером?
                                                      У ребят из соседнего проекта есть желание написать свой сериализатор для своего же асинхронного RPC, не требовавший бы отдельного компилятора языка вроде IDL (не знаю уж, чем им не нравится ProtoBuffers), т.е. имеется пожелание описывать структуру сообщений прямо на C++.
                                                      Ответить
                                                    • А можно немного приподнять завесу тайны над реализацией? Сам формат описывается в виде класса порожденного от шаблончиков отдельных семантик?
                                                      template <class D, const char *name, int size> class some_field_semantic {
                                                          // ...
                                                      };
                                                      class my_format : public <some_field_semantic<my_format, "test field", 6> > { };
                                                      Ответить
                                                      • >const char *name
                                                        Только мультибайт чар. смотри mpl::boost::string
                                                        Ответить
                                                    • А почему всё во время компиляции? Это что, для каждого формата своя копия функции чтения?
                                                      Ответить
                                                      • ты всё время считаешь это в "функциях", забывая, что в бинарнике это всё инлайнится в несколько mov, or и shr
                                                        Ответить
                                                        • Считывание целого файла инлайнится в несколько мов, ор, схр?
                                                          Или всё-таки зашаблонены лишь считывания фрагментов и они вызываются по указателю? А тогда зачем оно?
                                                          Ответить
                                                          • > Или всё-таки зашаблонены лишь считывания фрагментов и они вызываются по указателю?
                                                            Каждый get превращается в пару-тройку ассемблерных инструкций (если компилятор справился со своей работой), вызова функции по идее не останется (тело get'а заинлайнится в функцию обрабатывающую пакет. Т.е. этот код работает не хуже чем битфилды или ручная байтоёбля, но при этом легко модифицируется, и несложно запилить еще десяток форматов пакетов.
                                                            Ответить
                                                          • считывание "файла", равно как из сети и из других мест - это работа с буфером, к шаблону никак не относится
                                                            на принятый или созданный буфер накладывается этот шаблон (в его конструктор передается указатель), и ты получаешь оптимизированный доступ ко всем полям этого шаблона - умеешь их читать, писать
                                                            я же ниже показывал пример работы
                                                            в любой момент времени данные в буфере имеют соответствующее формату состояние, и этот буфер можно отправить в сеть/записать в файл и т.д.

                                                            объект "формата" не владеет буфером, задачи времени жизни, переполнения должны решаться снаружи
                                                            Ответить
                                                  • Вот взял бы эрланг и таких проблем с битовыми полями и рефлексией бы не было
                                                    Ответить
                                                    • > Вот взял бы эрланг и таких проблем с битовыми полями и рефлексией бы не было
                                                      Уйди, тролль, или реализуй тоже самое на эрланге.
                                                      Ответить
                                                    • я в курсе про эрланг
                                                      однако у нас не эрланг
                                                      как и в курсе про то, что рефлексии нет в крестах
                                                      да и 0-length проперти пригодились (ибо была палка о двух концах - либо доступ совсем "как к полю" - тогда объект разрастался бы с 4 байт до сотни (по 4 байта на каждую ссылку), ну или хер вам, а не "как к полю" - доступ как к методу

                                                      сейчас обрисую в общих чертах заложенные идеи
                                                      Ответить
                                                      • формат структуры задается в компайл-тайме, и в рантайме его с такими свойствами будет не собрать
                                                        итак
                                                        есть иерархия базовых типов, которые способны себя читать и писать по передаваемому смещению
                                                        template <size_t N> struct unsig {
                                                            enum { length = N, };
                                                            typedef ...<N>... value_type;
                                                            template <size_t Offset, bool Endianness>
                                                            static value_type get(void const * buf) { ... }
                                                            template <size_t Offset, bool Endianness>
                                                            static void set(void * buf, value_type const & v) { ... }
                                                        };
                                                        template <size_t N> struct array;
                                                        template <size_t N> struct string;

                                                        "семантика" поля - отдельный с++ тип, унаследованный от вышеописанных
                                                        например,
                                                        template <size_t N = 0> struct tag_field1: unsig<N> { static std::string get_static_name() { static std::string name = "field1"; return name; };
                                                        (@bormand - char const * же нельзя параметром шаблона:))
                                                        т.к. этих "семантик" куча, то проще объявлять их макросами вида
                                                        DECLARE(unsig, field1);
                                                        DECLARE(unsig, field2); //...

                                                        конкретный формат - выглядит примерно следующим образом:
                                                        pack<boost::mpl::list<
                                                            tag_field1<14>
                                                          , tag_field2<6>
                                                          , tag_field3<30>
                                                          , unnamed<unsig<4> >
                                                          , tag_field4<10>
                                                          , alignment_assert<32>
                                                          , tag_field5<16>
                                                        >::type, endianness::little>
                                                        Ответить
                                                        • этот тип pack<list...> самостоятельно "размещает внутри" себя "поля" - объекты вида pack_field<Item, Offset, Endianness, ...>, которые способны читать и писать уже реальное "поле" с учетом оффсета
                                                          наряду с pack_field есть специальные поля - специализированные на alignment_assert, pad_to_align, offset_assert, unnamed ...
                                                          кроме того, pack имеет "поиск" типа поля по "тегу" и по типу -
                                                          template <template <size_t> class What>
                                                          "some template magic"::ref find_by_tag() { ... } + const version
                                                          template <class T>
                                                          "another magic"::ref find_by_type() { ... } + const version
                                                          эти методы возвратят ссылку на реальное "поле" (ссылку на реальный pack_field), если этот тег/тип входят в состав формата, и ссылку на специальное поле, если не входит (компайл-тайм поиск по mpl::list)
                                                          ну и заодно pack хранит void */void const * (в зависимости мутабельный он или нет)

                                                          немного возникло проблем с сокращением размера объекта pack до sizeof(void *), да и "на лету" при обращении формировать поле pack_field не хотелось, хотелось именно ссылку возвращать
                                                          заодно выяснил, что вижуал студия отсасывает в категории empty base optimization :)

                                                          я совсем детали и дополнительные техники (типа поиска, или сравнения, или присваивания форматов) упустил, если нужны подробности, могу рассказать
                                                          Ответить
                                                          • ...<N>...
                                                            Зачем ты это сделал? Мне уже показалось это конструкцией языка вариадик темплейт из нового стандарта. Чуть мозг мне не вынес.
                                                            Ответить
                                                          • >(void const * buf)
                                                            buf - видимо raw data, где хранятся поля? А над другими типами кроме войда не думали?
                                                            Ответить
                                                          • ну и в итоге у меня есть некий враппер над любым форматом
                                                            format<Pack>, который имеет одноименные методы для всех используемых имен полей
                                                            {
                                                                "magic1"::ref field1() + const
                                                                "magic2"::ref field2() 
                                                                "magic3"::ref field3()
                                                            - тут тоже макросом всё сделано (их же несколько десятков) типа
                                                            FIELD_ACCESS(field1);
                                                            FIELD_ACCESS(field2);
                                                            FIELD_ACCESS(field3); // ...
                                                            что позволяет в итоге делать для объекта format<...> f; (имена условны)
                                                            f.something() = 100;
                                                            if (f.age() >= 30 && f.sex().exists()) f.name() = "Hello!";
                                                            т.е. то, что хотелось в "обобщенной" обработке любого формата

                                                            были бы в крестах проперти, убогие скобочки рядом с кошерными field_name можно было бы не писать (пичялька)
                                                            Ответить
                                                          • > этот тип pack<list...> самостоятельно "размещает внутри" себя "поля" - объекты вида pack_field<Item, Offset, Endianness, ...>

                                                            А можно взглянуть на код pack? Ума не приложу как разместить битовые поля. Я бы рекурсивно разместил их через наследование в каждом предке по полю, но так как важна точность до бита - у меня нет идей как это сделать, ибо наследование все нарушит
                                                            Ответить
                                                            • > как разместить битовые поля
                                                              в двух словах:
                                                              pack<list> это pack<list, offset = 0, list_not_empty = !mpl::empty<list>, ...>, который наследуется от 1) pack<mpl::pop_front<list>, offset + current_field_len, ...> - т.е. next_pack и
                                                              2) pack_field<mpl::front<list>, offset, ...>
                                                              где current_field_len - это pack_field<mpl::front<list>, offset, ...>::length

                                                              но в такой схеме множественного наследования 1) студия показывает дулю при оптимизации размера базовых классов (мол, историческая совместимость у них такая) и 2) не решена проблема, как pack_field будет иметь нулевой размер, но знать void *, с которым ему работать
                                                              поэтому в этом месте вынос мозга и используется base class chaining, т.е. pack наследуется от pack_field<...., next_pack>, а сам pack_field<..., NextType> наследуется от NextType (техника chaining была подсмотрена в boost.operators, когда решал проблемы с увеличением размера в студии на +1 на каждого предка)

                                                              соотв. есть финальная специализация pack<list, offset, empty = true>, которая "замыкая пидистал" хранит заодно и void */void const * и дает методы для доступа к ним (т.е. любой pack_field в стеке наследников выше имеет доступ к буферу).

                                                              в целом, это сложно понять с первого раза :)

                                                              отвечая на вопрос, почему void * - структуре все равно с сырой памятью работать, а к void * приводится любой другой указатель, который будут передавать в конструктор, про умные указатели pack не в курсе - пусть жизнью буфера управляет более внешняя сущность
                                                              Ответить
                                                              • >в целом, это сложно понять с первого раза :)
                                                                Нет, все прозрачно. Мастер класс удался. Мог бы даже повторить реализацию, если бы заняться было нечем. Спасибо.
                                                                Ответить
                                                          • Впрочем я все понял по своим вопросам. Можно не отвечать, кроме следующего:
                                                            > студия отсасывает в категории empty base optimization
                                                            Как проблему обходили?
                                                            Ответить
                                                          • Спасибо, в целом идея понятна. А pack_field'ы хранятся в статиках?

                                                            > @bormand - char const * же нельзя параметром шаблона
                                                            посыпал голову пеплом

                                                            P.S. Минуснувшему про эрланг - в эрланге битовый парсер хоть и удобен, но очень ограничен - например те же индейцы настраиваются только у отдельных полей, а не в целом на формат, нет удобного парсинга строки и т.п. Все эти мелочи и преврятят красивую идею переписать все на эрланге в говно.
                                                            Ответить
                • > я минусую только матерщину.
                  какого хуя?
                  Ответить
              • между прочим, в красноглазой говнореализации stl (g++) 2005 года действительно достойно говнокода
                /**  Returns the number of elements in the %list.  */
                      size_type
                      size() const
                      { return std::distance(begin(), end()); }
                Ответить
                • >std::distance<InputIt> - Complexity Linear, however, if InputIt additionally meets the requirements of RandomAccessIterator, complexity is constant. Так что стандарт или не стандарт, а в некоторых stl это точно O(n).
                  Ответить
                  • для списка то? там явно бидирекшионал, и поэтому O(n)
                    я бы сильно удивился, если бы лист где-нибудь реализовали как массив
                    Ответить
                    • > там явно бидирекшионал, и поэтому O(n)
                      Капитан
                      Ответить
                    • > я бы сильно удивился, если бы лист где-нибудь реализовали как массив
                      В C# List реализован как std::vector
                      Ответить
                      • а причем тут шарп? в шарпе тот лист, что аналог плюсового std::list скорее LinkedList, чем List.
                        Ответить
                    • > я бы сильно удивился, если бы лист где-нибудь реализовали как массив
                      А это возможно? Он не подойдёт под ТЗ, конкретно под пункты про алгоритмическую сложность вставки.
                      Ответить
                    • всегда казалось, что питоний "list" реализован через массив (правда динамический)
                      Ответить
                      • А здесь просто конфликт терминологий. Одни (например Тарас) считают, что list это именно linked list, у которого вставки и удаления работают за O(1), и медленный доступ по индексу за O(n). Другие (например разрабы библиотек жабы и пистона) считают лист просто абстрактным списком, которому простительно делать вставки за O(n) и индексированный доступ за O(1).
                        Ответить
          • >>чем то серьезно отличается проверка size_t от проверки bool
            1. Переход на другую реализацию STL, в которой container::size() вычисляется медленнее, чем container::empty()
            2. Смена типа контейнера, у которого --//--
            3. container.empty() "читаемей", чем 0 == container.size()
            Обо всем этом писал Мейерс. Или таки в стандартной библиотеке неожиданно обнаружился лишний код и container::empty() на самом деле не нужен.
            Ответить
    • Новичок:
      list<int> list;
      ...
      for(auto i=0;i<list.size();i++){
          auto item = *next(list.begin(), i);


      Продвинутый новичок, узнавший слово "оптимизация":
      list<int> list;
      ...
      if(list.size() != 0)
          for(auto i=0;i<list.size();i++){
              auto item = *next(list.begin(), i);
      Ответить

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