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

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 87
  88. 88
  89. 89
  90. 90
  91. 91
  92. 92
  93. 93
  94. 94
  95. 95
  96. 96
  97. 97
  98. 98
  99. 99
  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 Koshak90, (Updated )

Комментарии (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-е схема рядом с данными?
        Ответить
          • Эти "ненужные" номера полей как раз позволяют не париться с версиями. Кроме того, так решается проблема, которую версии решить не могут: чтение новой версии данных старой версией софта.
            Ответить
                • Да я неправильно прочёл фразу "новой версии данных старой версией софта". Потом перечитал и стёр ответ.
                  Ответить
            • Номер версии четко определяет протокол, а с этими номерами полей возиться надо, думать, совместимо ли со старыми версиями изменение в протоколе, которое собираешься сделать. И версионирование позволяет вносить любые изменения в протокол, в отличие от.

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

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

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

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

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

                Если есть 100500 batch-задач, которые обрабатывают массив данных, записанный другой программой, то такой подход очень даже хорошо работает. Именно в таких условиях протобуф и создавали.
                Ответить
                • Я представил, о чем речь. Типа чтобы всякие скрипты не обновлять при изменениях в генераторе данных. Наверное для этой задачи оно кстати. Но это не отменяет версионирования и, наверное, не должно быть по-дефолту (оверхед же).
                  А то я видел, как некоторые товарищи воспринимают протобуф, как серебрянную пулю, решающую проблему обратной совместимости, а потом "ой, ну мы тут протокол сломали, обновитесь".
                  Ответить
      • > это для сетки, для диска не предназначено

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

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

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

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

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

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

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

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

                Пошёл полистать Concept-Lite. В общем это просто предикаты на типах, компилятор не проверяет, что используются только те операции, которые были разрешены. Да не сможет он, ибо шаблон с концептами должен в теории уметь вызывать шаблоны без концептов, а там уж не известно заранее, что происходит. Это как типизацию к питону постфактум прикручивать.
                Ответить
            • gcc начиная с 6.1 емнип поддерживает с флагом -concepts или -fconcepts
              Ответить
      • Концепт представляет из себя набор условий, налагаемых на тип. Вкусного в нем лаконичность использования (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) выполняется, в отличие от указанного в статье.
                  Ответить
          • > мета-питушня
            Я официально нарёк это словом "Метушня". Будьте добры использовать мой форсед мем.
            Ответить
            • Метушня - это метаданные, а мета-петушня - это метопрогроммирование. Я решил, что это разные вещи, но если ты настаиваешь на более широком смысле термина метушня, то я не против.
              Ответить

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

Из-за тебя ушел bormand, guest!

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


    8