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

    +18

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    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
    class figure
    {
    //...
    };
    
    class triugolnik: public figure
    {
    //...
    };
    
    class kvadrat: public figure
    {
    //...
    };
    
    #define PAIR(f0, f1) std::make_tuple(std::type_index(typeid(f0)), std::type_index(typeid(f1)))
    
    int PloshadTrehFigur(const figure& f0, const figure& f1, const figure& f2);//forward declaration
    int PloshadDvuhFigur(const figure& f0, const figure& f1)
    {
      static const std::unordered_map<
        std::tuple<std::type_index, std::type_index>, std::function<int(const figure&, const figure&)> 
      > caller 
        {
           {PAIR(triugolnik, kvadrat), ploshadTriugolnikIKvadrat},
           {PAIR(kvadrat, triugolnik), lispGovno::flip(ploshadTriugolnikIKvadrat)},
           {PAIR(kvadrat, kvadrat), ploshadKvadratIKvadrat},
           {PAIR(triugolnik, triugolnik), ploshadTriugolnikITriugolnik}
        };
        const auto& f = caller.find(PAIR(f0, f1));
        assert(f!=caller.end());
        f(f0, f1);
    }
    
    #undef PAIR

    Наш ответ Чемберлену:
    http://govnokod.ru/13933
    lispGovno::flip - flip такой же как в хаскель из моей особой мегабиблиотеки победителя каждый день.
    Шах и мат господа присяжные засидатели. Мультиметоды в крестах есть и реализуются за 5 минут.
    В сишке аналогично. Все анскилябры залезли под кровати.
    Визитары размазанные по коду сосут и трудно поддерживаются.

    Запостил: LispGovno, 20 Ноября 2013

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

    • / Тхред
      Ответить
    • Квадратичное говно (n*n, где n - число сабклассов figure)... До полноценных мультиметодов этому коду как до луны пешком ;)

      К примеру, в данной схеме нельзя написать "обобщенные" версии функции, у которых в аргумент может приходить не только некий класс, но и все его потомки. Это спасло бы от квадратичного разрастания, если функции для работы вполне хватает базового класса:
      class polygon : public figure {}
      class triange : public polygon {}
      class rectangle : public polygon {}
      // ...
      { PAIR(polygon, polygon), ploshadDvuhPoligonoff } // обобщенная версия
      { PAIR(rectangle, rectangle), ploshadDvuhPryamougolnikoff } // специфичная версия, например более быстрая
      А диспетчеризация по "специфичности", емнип, одна из основных фич мультиметодов ;)
      Ответить
      • А ты как сам то? Неквадратичное говно сможешь написать без убогих размазанных по коду визитаров читаемых как черная татуировка на черной заднице нигера? И нихрена оно у меня не квадратичное. Зеркальные пары реализовывать ни нужно.
        Ответить
        • Для такого есть common lisp
          Ответить
          • ты так говоришь как-будто в крестах или жабе никогда не нужны мультиметоды
            Ответить
            • Никто не чувствует их недостатка кроме здешних извращенцев.
              Ответить
              • А ты знаешь чем можно заменить мультиметоды или визитор? Стандартный паттерн. Используется довольно часто.
                Ответить
                • Не использую шаблоны проектирования из принципа.
                  Ответить
                  • http://www.fsfla.org/~lxoliva/fun/prog/resign-patterns
                    Ответить
                    • показать все, что скрыто— раздался пронзительный голос со стороны параши.

                      Но пацаны, как всегда, не обратили внимания на это визгливое кукареканье. Пусть кукарекает, что с него взять?

                      Петух — не человек, и сегодня ему предстоит очень трудная ночь. У него уже в течение полутора лет каждая ночь была очень трудной, и теперь его анус был разработан настолько, что он без труда мог спрятать в нём банку сгущёнки.
                      Ответить
                    • Ты решил, что раз он не использует паттерны, то тогда он использует антипаттерны? Ну не лишено смысла
                      Ответить
        • > Зеркальные пары реализовывать ни нужно.
          О да, n^2 квадратичное, а n*(n-1)/2 не квадратичное...

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



            А отсортировать сами классы по специфичности во время компиляции?
            Ответить
            • > А отсортировать сами классы по специфичности во время компиляции?
              А как? В крестах же иерархию классов ни при компиляции (т.к. они могут быть в других файлах и даже дллках), ни даже в рантайме не выяснить. Можно только проверить факт наследования через dynamic_cast, да реальный тип через typeid...

              Имея ссылку на figure легко проверить, является ли оно rectangle или polygon, но вот понять, что rectangle более специфичный чем polygon - никак.

              Остается только руками добавлять в классы дополнительную инфу, например std::type_index родителя (если забить на множественное наследование) ;(
              Ответить
              • Вот такой вариант пока пришел в голову (о комбинировании функций аля CLOS пока не мечтаем): ищем в мапе точное совпадение, если не нашлось, апкастим крайний правый аргумент, ищем правило, если добрались до верха иерархии и не проканало - восстанавливаем правый аргумент, и начинаем апкастить следующий (аля полный перебор)... Если нашли - добавляем точные типы в мап, чтобы в следующий раз поиск прошел за одну итерацию.

                Например пусть у нас есть:
                (polygon, polygon) - универсальная функция
                (rectangle, polygon), (polygon, rectangle) - более быстрые реализации

                Тогда (rectangle, triangle) заматчится с (rectangle, polygon) после апкаста triangle в polygon. В мап добавится (rectangle, triangle), ссылающийся на ту же ф-ю что и (rectangle, polygon).
                А в (triangle, rectangle) апкаст правой части не даст ничего, поэтому апкастим левый, и получаем (polygon, rectangle). В мап добавится (triangle, rectangle) ссылающийся на функцию от (polygon, rectangle).
                Ответить
              • > А как? В крестах же иерархию классов ни при компиляции (т.к. они могут быть в других файлах и даже дллках), ни даже в рантайме не выяснить.
                А зачем это выяснять? У тебя есть список функций, обрабатывающих пары или тройки и тд. Вытащил из них сигнатуры. Из сигнатур вытащил типы параметров. Отсортировал их по специфичности. Дальше уже дело в шляпе. Наверное O(1) при такой постановке задачи уже не получится сделать, хотя надо подумать. Но иерархии обычно не большие, так что это не проблема.
                Ответить
                • > Отсортировал их по специфичности
                  Как? Я же не могу узнать кто там от кого порожден. Даже в рантайме. Ну вот только если программист будет добавлять некую инфу о родителях класса вручную.

                  > Наверное O(1) при такой постановке задачи уже не получится сделать
                  Да хуй с ним с O(1) :) Даже в CL это поиск с последующим кешированием.
                  Ответить
                  • > Как? Я же не могу узнать кто там от кого порожден

                    Только топосорт, где в качестве отношения - приводимость
                    Ответить
                    • Но приводимость тестится только динамик_кастом, а его можно вызывать только на настоящем объекте, reinterpret_cast<T*>(null) не пройдет ;) В этом и трабла ;) Или я ошибаюсь?

                      Я пока вижу только одно решение руками (например макросом PARENTS(foo, bar)) или досборочным скриптом прикручивать к классам дополнительную инфу...

                      Ну и сортировка очень плохо сочетается с динамически подгружаемым кодом.
                      Ответить
                      • > отсортировать сами классы по специфичности во время компиляции?

                        Если я ничего не путаю в вашей беседе, то std::is_convertible должен сойти. В гениальных плюсах правда могут быть циклы в операциях приведения: a конвертится в b, b конвертится в a, т.е. это отношение уже не является отношением weak ordering
                        Ответить
              • В языке типа Ц++ с его ООП такое просто не получится. В КЛОС такое возможно только потому, что есть механизм, который гарантирует что построение иерархии для данного класса закончилось (mop:finalize-inheritance). До того, как кто-то этот метод у класса не вызовет, иерархию не рассчитать никак. А чтобы его вызвать, нужно чтобы компилятор был доступен лексеру (в Ц++ это не возможно по самой природе языка, т.как шаблоны мешают).
                Ответить
    • http://habrahabr.ru/post/155515/

      Видел?
      Ответить
      • > В следующей статье я покажу, как задать собственную стратегию приведения типа на примере «fast_cast», которая рвет по эффективности dynamic_cast на порядки.

        Я люблю реализовывать операторы языка каждый день. У операторов С++ есть один фатальный недостаток. Создатели компилятора слишком тупые. А я свободный от задротства человек, успешен по жизни и реализую операторы языка 3 раза в день.
        Ответить
        • У авторов llvm тоже есть свой dyn_cast с isa и скоростью.
          http://llvm.org/docs/doxygen/html/Casting_8h_source.html
          Ответить
          • isa - Industry Standard Architecture Bus?

            Зачем это им вообще было нужно? В компиляторе не так часто нужно кастить типы. Оптимизация рут о эвил головного мозга?
            Ответить
            • Архитектура автобуса?
              Ответить
            • Думаешь, нечасто? Мне кажется, это вполне распространённая операция при работе с AST.
              Ответить
      • Судя по иерархии - без множественного наследования и без использования специфичности о которой говорил forman - можно было добиться O(1) вместо убого dynamic_cast.
        Не удивлюсь, если эта библиотека не умеет в специфичные мультиметоды, не умеет во множественное и виртуальное наследование и ещё что-нибудь.
        Ответить
        • Ты всё ещё веришь, что в плюсах можно написать что-то, что будет корректно работать со всеми возможностями языка?
          Я не верю. Потому считаю, что незамысловатый ограниченный в возможностях велик как правило лучше громоздких универсальных решений и ближе к телу.
          Ответить
          • Ну что мне тебе ответить?

            Ты меня затролил. И ты везде прав.
            Ответить
    • Тут тоже такое было, но я повторюсь.
      Из моего арканоида.
      switch (TO_PAIR(t1,t2))
      			{
      			case TagPair<Alga,Brick>  ::value :
      			case TagPair<Alga,Bat>    ::value :
      			case TagPair<Alga,Ball>   ::value :
      			case TagPair<Alga,Bullet> ::value :
      			case TagPair<Bat,Bonus>   ::value : 
      ...

      При этом TagPair устроен так, что TagPair<Bullet,Alga>, например, тупо не скомпилируется, это даст контроль над зеркальными парами.
      Ответить
      • Ссылка на код осталась? Ну или запости подробнее
        Ответить
        • Тут где-то было такое про игральные карты.
          Ответить
    • Товарищи, не знаете ли вы, API PulseEvent не вызывает дисбаланс какого нибудь счетчика? Уместно ли будет запихнуть его в таймер?
      Ответить
      • Почему бы и нет? Оно, емнип, просто будит один или несколько потоков, спящих на ивенте.
        Ответить
    • >>triugolnik
      >>ploshadTriugolnikITriugolnik
      Блджад, немедленно развидеть это!!!
      У меня ТРИУГОЛЬНИК от такого безграмотного транслита.
      Ответить

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