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

    −14

    1. 001
    2. 002
    3. 003
    4. 004
    5. 005
    6. 006
    7. 007
    8. 008
    9. 009
    10. 010
    11. 011
    12. 012
    13. 013
    14. 014
    15. 015
    16. 016
    17. 017
    18. 018
    19. 019
    20. 020
    21. 021
    22. 022
    23. 023
    24. 024
    25. 025
    26. 026
    27. 027
    28. 028
    29. 029
    30. 030
    31. 031
    32. 032
    33. 033
    34. 034
    35. 035
    36. 036
    37. 037
    38. 038
    39. 039
    40. 040
    41. 041
    42. 042
    43. 043
    44. 044
    45. 045
    46. 046
    47. 047
    48. 048
    49. 049
    50. 050
    51. 051
    52. 052
    53. 053
    54. 054
    55. 055
    56. 056
    57. 057
    58. 058
    59. 059
    60. 060
    61. 061
    62. 062
    63. 063
    64. 064
    65. 065
    66. 066
    67. 067
    68. 068
    69. 069
    70. 070
    71. 071
    72. 072
    73. 073
    74. 074
    75. 075
    76. 076
    77. 077
    78. 078
    79. 079
    80. 080
    81. 081
    82. 082
    83. 083
    84. 084
    85. 085
    86. 086
    87. 087
    88. 088
    89. 089
    90. 090
    91. 091
    92. 092
    93. 093
    94. 094
    95. 095
    96. 096
    97. 097
    98. 098
    99. 099
    100. 100
    #ifndef RPCCALL_H
    #define RPCCALL_H
    #include <deque>
    #include <typeinfo>
    #include <string>
    #include "byteinbuffer.h"
    #include <byteoutbuffer.h>
    #include <ostream>
    class RPCPack
    {
    public:
        RPCPack();
        //RPCPack(const RPCPack &obj);
        RPCPack(RPCPack && obj);
        RPCPack & operator = (RPCPack&& obj);
        template<class T, typename std::enable_if<
            std::is_pod<T>::value && !std::is_pointer<T>::value>::type* = nullptr>
        bool pack(const T& param);
        template <class T,typename std::enable_if<
                      std::is_same<typename T::iterator::iterator_category,std::random_access_iterator_tag>::value>::type* = nullptr>
        bool pack(const T& param);
    
        template <class T,typename std::enable_if<
                      std::is_same<typename T::iterator::iterator_category,std::bidirectional_iterator_tag>::value>::type* = nullptr>
        bool pack(const T& param);
    
        template <class T,typename std::enable_if<
                      std::is_same<typename T::iterator::iterator_category,std::forward_iterator_tag>::value>::type* = nullptr>
        bool pack(const T& param);
    
        template<class D,class ... T >
        bool pack(const D& param,const T& ... params);
    
        template<class ... T>
        bool pack(const T& ... params);
    
        template<class T, typename std::enable_if<
            std::is_pod<T>::value && !std::is_pointer<T>::value &&  !std::is_array<T>::value>::type* = nullptr>
        bool unpack(T& param);
    
        template <class T,typename std::enable_if<
                      std::is_same<typename T::iterator::iterator_category,std::random_access_iterator_tag>::value>::type* = nullptr>
        bool unpack(T& param);
    
        template <class T,typename std::enable_if<
                      std::is_same<typename T::iterator::iterator_category,std::bidirectional_iterator_tag>::value>::type* = nullptr>
        bool unpack(T& param);
    
        template <class T,typename std::enable_if<
                      std::is_same<typename T::iterator::iterator_category,std::forward_iterator_tag>::value>::type* = nullptr>
        bool unpack(T& param);
    
    
        template<class D,class ... T >
        bool unpack(D& param, T& ... params);
    
        template<class ... T>
        bool unpack(T& ... params);
        template <class T,class D>
        bool pack(const std::pair<T,D> & p);
        template <class T,class D>
        bool unpack(std::pair<T,D>& p);
        std::vector<char> getSerialized();
    
        void deserialize(std::istream &vs);
        size_t getSize();
        bool isEmpty();
        void copyOuttoIn();
        void moveOuttoIn();
        ByteOutBuffer<char> getBuffer() const;
        void setBuffer(const ByteOutBuffer<char> &value);
    
    private:
        std::deque<size_t> sig;
        std::vector<char> outdata;
        std::vector<char> indata;
        ByteOutBuffer<char> outbuffer;
        ByteInBuffer<char> inbuffer;
        std::istream is;
        std::ostream os;
    };
    
    
    template<class T, typename std::enable_if<
        std::is_pod<T>::value && !std::is_pointer<T>::value>::type*>
    
    bool RPCPack::pack(const T& param)
    {
       sig.push_back(typeid(param).hash_code());
      if(os.write((char*)&param,sizeof(param)))
          return true;
      return false;
    }
     template <class T,class D>
    bool RPCPack::pack(const std::pair<T,D>& param)
    {
       return pack(param.first) & pack(param.second);
    }
    
    template <class T,class D>

    Хуячу сериализацию. Я метапрограммер)

    Запостил: Koshak90, 16 Января 2017

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

    • Очень мерзкий код. Мне настолько неприятно его видеть, что я побрезговал бы просиживать штаны с тобой в одном опенспейсе.
      Зачем ты его написал? Это шутка или всерьез? Ведь если ты запостил его сюда, то понимаешь, что это говно. Было бы интересно послушать, что именно ты думаешь о своем творении. Какие именно места тебе кажутся плохими? Или ты запостил его, чтобы похвастаться?
      Ответить
      • тут плохо всё) Какая задача такой и код, Чувак. А что плохого здесь ты видишь?
        Ответить
        • Ну давай разберем по частям тобою написанное.
          1) Ты захардкодил методы pack и unpack в классе вместо того, чтобы сделать их свободными функциями и дать пользователю возможность переопределять их для своих типов.
          2) Очевидно, твой сериализатор сосет по перфомансу, потому что данные 100500 раз копируются между буферами, дофига аллокаций из кучи, которые пользователь не контролирует, используются стремные иостримы. Хороший сериализатор не аллоцирует вектор, а пишет в буфер или стрим пользователя.
          3) Непонятно, почему в одном классе смешана в кучу сериализация и десериализация.
          4) Твоя сериализация не только зависит от архитектуры (порядок байт в структурах), она зависит от компилятора (паддинг).
          5) > pack(param.first) & pack(param.second)
          Выучи разницу между битовыми и логическими операциями.
          Ответить
    • > if(os.write((char*)&param,sizeof(param)) )

      Вот так изящно всё, что уже сериализовано на диск, превращается в мусор, когда в структурке добавляются / меняются поля.
      Чего только люди не придумают, лишь бы не использовать Protocol Buffers / https://capnproto.org/ и прочие MMS
      Ответить
      • Сейчас придет СНаУТ и скажет, что схема рядом с данными не нужна, а описанная тобой проблема решается версионированием.
        На самом деле это я сказал, прикрывшись снаутом.
        Ответить
        • > схема рядом с данными не нужна

          А где в protobuf-е схема рядом с данными?
          Ответить
          • Ну там какие-то ненужные номера полей и хранятся типы этих полей.
            https://developers.google.com/protocol-buffers/docs/encoding#structure
            Ответить
            • Эти "ненужные" номера полей как раз позволяют не париться с версиями. Кроме того, так решается проблема, которую версии решить не могут: чтение новой версии данных старой версией софта.
              Ответить
              • Ответить
                • Мне сообщения в личку не приходят, если что.
                  Ответить
                  • Да я неправильно прочёл фразу "новой версии данных старой версией софта". Потом перечитал и стёр ответ.
                    Ответить
              • Номер версии четко определяет протокол, а с этими номерами полей возиться надо, думать, совместимо ли со старыми версиями изменение в протоколе, которое собираешься сделать. И версионирование позволяет вносить любые изменения в протокол, в отличие от.

                > чтение новой версии данных старой версией софта

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

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

                  Я говорю о чтении старой версией программы данных, которые были записаны с новой версией схемы. Никакого сервера при этом нет.

                  > подход протобуфа более костыле-ориентированный

                  Если есть 100500 batch-задач, которые обрабатывают массив данных, записанный другой программой, то такой подход очень даже хорошо работает. Именно в таких условиях протобуф и создавали.
                  Ответить
                  • Я представил, о чем речь. Типа чтобы всякие скрипты не обновлять при изменениях в генераторе данных. Наверное для этой задачи оно кстати. Но это не отменяет версионирования и, наверное, не должно быть по-дефолту (оверхед же).
                    А то я видел, как некоторые товарищи воспринимают протобуф, как серебрянную пулю, решающую проблему обратной совместимости, а потом "ой, ну мы тут протокол сломали, обновитесь".
                    Ответить
      • это для сетки, для диска не предназначено. Тут я ещё наговнокодил hashcode который нифига не точен http://en.cppreference.com/w/cpp/types/type_info
        Ответить
        • > это для сетки, для диска не предназначено

          Разница не принципиальна. Вполне может оказаться, что на разных концах канала передачи данных разные версии софта.
          Ответить
          • > Разница не принципиальна.
            Для сетки, имхо, даже хуже ;)

            На диске это ещё можно было бы списать на пирфоманс (у той же постгри, емнип, базу нельзя таскать на другие машины из-за такой вот привязки к архитектуре/компилеру). А в сетке как минимум машины с x86 и amd64 обязательно попадутся...
            Ответить
            • архитектура только одна на сервере и клиенте даже одна ось другой не будет
              Ответить
              • > даже одна ось другой не будет
                Инфа 100%?
                Ответить
                • 100%. Там же этот софт не запустится, придётся ставить точно такую же ось вечно :3
                  Ответить
                  • А исходники автор сразу удалит, потому что стыдно.
                    Ответить
                    • Надо сделать конпелятор, который удаляет исходник сразу после его конпеляции.
                      Ответить
                      • вместе с автором
                        Ответить
                        • Зачем? Пусть набирает ещё и ещё раз, как Сизиф...
                          Ответить
                          • Я, кстати, знавал таких чуваков которые заново набирали.
                            Они не умели VCS, не умели модульность, и каждую свой мегапроект писали с нуля.

                            Ну правда это были школьники (в буквальном смысле) ;)
                            Ответить
                            • > знавал таких чуваков которые заново набирали
                              А у меня на приставке с бейсиком некуда было сохранять проги...
                              Ответить
                              • У меня тоже. К счастью, я умел писать примерно одну программу: "угадай число". С циклом, RANDOM(), и INPUT.

                                А ее легко было набрать по памяти. Все семь строк.
                                Ответить
                              • Собрал бы робота набирателя программ по перфокартам. Ты же борманд.
                                Ответить
                      • Спектрумолюб.
                        Ответить
    • *снаут сказал "ASN.1" и укрылся в окопе*
      Ответить
      • мне было впадлу его реализовывать
        Ответить
        • > впадлу его реализовывать
          Как что-то плохое. Не хотеть писать свою реализацию ASN.1 - совершенно нормально.

          З.Ы. Готовые либы запрещено юзать?
          Ответить
          • openssl есть
            Ответить
            • Ну вот, кстати, в openssl есть неплохой сериализатор для ASN.1. Правда сишный и на макросах.
              Ответить
              • а под линь помоему ничего лучше нету.
                Ответить
                • видел телекомных профи которые за пару часов кастом парсер ASN.1 писали. в 80х/90х ASN.1 это был почти XML.

                  с другой стороны, кодирование данных в ASN.1 говно. если не знаешь заранее что за данные - то и не распарсишь, и незнакомые поля не перепрыгнешь. я лично пользуюсь TLV. все на меня ругаются за это - потому что "медленно" и "избыточно" - но мне нравится.
                  Ответить
    • у кого-нибудь остался вопрос "почему нужны концепты"?
      Ответить
      • По-моему не нужны.
        Ответить
      • честно говоря я так до сих пор и не понял что такое концепты.

        раньше думал что это нечто что помогает интерфейсы/этц темплейтов компилеру верифицировать - и еще до инстанциирования. но как выяснилось это не оно.
        Ответить
        • > но как выяснилось это не оно
          Откуда выяснилось?
          Ответить
          • на паре проектов видел. загадочные пустые структуро-темплейты, которые никакого эффекта не имели. интерфейсы случайно ломали - толку от концептов не было никакого.
            Ответить
            • > на паре проектов видел

              У вас был компилятор с поддержкой концептов? Сомневаюсь.
              Если использовали BOOST_CONCEPT_CHECK, то это не совсем то. Он не проверяет, что в шаблоне не используется то, что не заявлено в требованиях. Вообще всё это похоже на "опциональные тайп-хинты", попытку прикрутить типизацию к языку, в котором её изначально не было. Много вопросов возникает.
              Ответить
              • ЕМНИП, концепт - это же практически кусок кода, который должен компилироваться, чтобы концепт выполнялся. Там просто действия с переменной записаны. Предполагается, что компилятор сможет выводить корректность шаблона из такого концепта?
                И разве шаблон может использовать только то, что написано в концепте?
                Ответить
                • > Предполагается, что компилятор сможет выводить корректность шаблона из такого концепта?

                  Пошёл полистать Concept-Lite. В общем это просто предикаты на типах, компилятор не проверяет, что используются только те операции, которые были разрешены. Да не сможет он, ибо шаблон с концептами должен в теории уметь вызывать шаблоны без концептов, а там уж не известно заранее, что происходит. Это как типизацию к питону постфактум прикручивать.
                  Ответить
              • gcc начиная с 6.1 емнип поддерживает с флагом -concepts или -fconcepts
                Ответить
                • надо будет побаловатся.

                  дока к концептам есть где? потому что когда гуглишь "кресты концепции" находится только мусор.
                  Ответить
                  • https://en.wikipedia.org/wiki/Concepts_(C%2B%2B) ?
                    Ответить
                    • когда я туда смотрелся, оно выглядело приблизительно вот так:

                      https://en.wikipedia.org/w/index.php?title=Concepts_(C%2B%2B)&oldid =696409818

                      и было каким-то более или менее теоретическим Г. я еще тогда смотрелся в сырцы STL где якобы были какие-то концепции, но там точно так же ничего интересного не было.
                      Ответить
                  • > когда гуглишь "кресты концепции" находится только мусор

                    Ну ктож так гуглит
                    https://isocpp.org/blog/2013/02/concepts-lite-constraining-templates-with-predicates-andrew-sutton-bjarne-s
                    Там есть ссылки на PDF и гуглодоки с более подробным описанием.
                    Ответить
                    • в коментах сидит вот это:

                      http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3351.pdf

                      133 страниц счастья.
                      Ответить
        • Концепт представляет из себя набор условий, налагаемых на тип. Вкусного в нем лаконичность использования (void foo(Container &c) {...}) и возможность проверки выполняемости не только по type traits, но и по семантической корректности выражений ({ a.begin() } -> Iterator ). По факту, отличие между void foo(Container &c) {...} и void foo(auto &c) {...} только в проверке выполнения требований концепта
          Ответить
          • Шаблонная мета-питушня не нужна. А в тех редких случаях, когда нужна, можно и енабле_ифами обойтись.
            Ответить
            • Вернее, я даже не против чего-то подобного, но не в таком убогом виде. Завезли бы нормальные тайпклассы, было бы другое дело. А так - говнокостыли какие-то.
              Ответить
              • > говнокостыли

                как раз для тех кто слишком долго ходил по крестам.

                степени мазохизма: ходил по лего, ходил по граблям, ходил по крестам.
                Ответить
                • Меня реально напрягает то, в каком направлении движется крестосообщество. Существует целая армия экспертов-дармоедов, которые ведут бложики и пишут огромные простыни не о реальных прикладных проблемах, а о крестоебле. А комитет похоже всерьёз собирается довести сложность плюсов до такой степени, чтобы по ним можно было писать диссертации.
                  Больше ненужных фич богу ненужных фич!
                  Ответить
                  • До Malbolge крестам ещё далеко, так что пока ещё есть простор для развития.
                    Ответить
                  • посмотри на того же маерса. чудак умный - а толкает примитивное говно. потому что умные вещи сложнее продавать чем примитивное говно. а деньги зарабатывать нужно.

                    умные вещи можно продавать только умным. но умным продать что ли бо сложно, потому что в конце часто все сводится к "all is good in moderation". и поиск этого самого moderation в книжках не вычитаешь - это зависит от приложений/людей/прикладной области. с чем теоретические материалы не сильно помогают.
                    Ответить
                    • > толкает примитивное говно

                      Спорное утверждение. В чём говно-то? Мне, вообще говоря, нравились его книги, когда я только начинал учить кресты. Гораздо лучше многого из того, что можно найти по той же жабе.
                      Ответить
                      • слово "говно" было употреблено в смысле "нечто бесполезное" (с легким преувеличением).

                        я его книжек не читал, но догадываюсь что они будут ОК, потому что он более прагматичный чудак. (его уже имеет смысл критиковать, по сравнению с толпами пустых мест.) я читал его лекции/презентации с воркшопов по С++ в паре прикладных областей. если ни разу в универ не ходил - то они может быть и полезны, но по уровню они CompSci 101/201, и не более.
                        Ответить
                        • Приведи пару примеров, пожалуйста. Я спрашиваю из интереса, а не намерения поспорить.
                          Ответить
                  • Я топчусь около компьютеров с конца 90х, и всё это время слышу что кресты это сложное, мутное говно, в котором никто толком не разбирается, и что с каждым новым стандартом в них всё больше мутной херни.

                    При этом кресты цветут и пахнут, а крестопрограммисты остаются одними из самых высококлассных программистов в мире.

                    В чём секрет?
                    Ответить
                    • До 2011 года комитет выпустил 1.07 (одна целая и семь сотых) стандартов, так что притензии вроде моих ты тогда слышать не мог.
                      Ответить
                      • Ну стандарты -- да, но про "сложность" еще автор рубей писал, и писал еще в 1993м году: дескать я пишу на крестах нескока лет и всё еще они меня удивляют
                        Ответить
                        • Тут уж мне сложно судить. Я тех плюсов не видел и вообще еще молод и дерзок.
                          Ответить
              • http://sms.cs.chalmers.se/publications/papers/2008-WGP.pdf
                Сравнение тайплассов хаскеля и концептов с++ (проползал из c++0x, едва ли Concepts TS много в чем хуже). Вывод автора статьи:
                Out of our 27 criteria, summarised in table 2, 16 are equally supported in both languages, and only one or two are not portable. So, we can safely conclude as we started — C++ concepts and Haskell type classes are very similar.
                Мой вывод: вы, сударь, говноглор
                Ответить
                • Своих мыслей-то нет? Вся суть крестофанбоя.
                  Ответить
                  • Ну ежели навороченные концепты из этой статьи смотреть, а не Concept-Lite, там вроде не просто предикаты на типах. Похоже, что компилятор видит требования к типам и может их энфорсить. Тогда действительно не сильно от тайпклассов отличается.
                    Ответить
                  • свои мысли-то есть, но зачем тебя добивать? Например, я знаю, что в плюсах можно явно инстанцировать специализацию шаблона, поэтому требование 6.3 из таблицы 2 (Separate compilation) выполняется, в отличие от указанного в статье.
                    Ответить
            • > мета-питушня
              Я официально нарёк это словом "Метушня". Будьте добры использовать мой форсед мем.
              Ответить
              • Метушня - это метаданные, а мета-петушня - это метопрогроммирование. Я решил, что это разные вещи, но если ты настаиваешь на более широком смысле термина метушня, то я не против.
                Ответить

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