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

    +32

    1. 1
    2. 2
    3. 3
    4. 4
    typedef typename _STD tr1::conditional<
            _STD tr1::is_same<key_type, value_type>::value,
            const_iterator,
            _Tree_iterator<_Mybase> >::type iterator;

    Шаблоны на шаблонах и шаблонами погоняют.

    Запостил: Fai, 14 Июля 2012

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

    • И чо? Всё тут верно.
      Ответить
      • Красивый, понятный код, в духе KISS, не находите?
        Ответить
        • Слабо сделать проще?
          Ответить
          • Во время компиляции решить, какой итератор юзать исходя из типов ключа и значения... Да, слабо. А вам?
            Ответить
            • Сейчас кто-то соснет
              Тайпклассы
              .
              Ответить
              • > Сейчас кто-то соснет
                Это вы про меня? Тогда пример переделанного кода в студию. Он же простой, много времени у вас не отнимет ;)
                Ответить
                • показать все, что скрыто"Напиши код. Напиши его еще раз" - это путь крестопедика, белый же человек знает про code reuse и traversable:
                  http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Traversable.html
                  http://www.scala-lang.org/api/current/scala/collection/Traversable.html
                  Ответить
                  • > code reuse и traversable
                    Лолчто?

                    А для чего по-вашему служат итераторы? А они же, внезапно, и есть обобщенный интерфейс для обхода коллекций. Причем для языков, в которых без извратов не описать лямбду или хотя бы локальную функцию (привет Тарас), итераторы на порядок юзабельнее нежели traversable.

                    Теперь про коде reuse: в ваших любимых Хаскеле и Скале реализацию traverse и sequenceA пишет Александр Сергеевич Пушкин? Нет. Ее пишет автор контейнера, как и здесь. Использование conditional и is_same для вас тоже не code reuse?
                    Ответить
                    • привет
                      Ответить
                      • Чёзанах, он по делу сказал, а я спетросянил, какого хуя у меня плюсов больше?
                        Ответить
                        • Ну, возможно, я в чем-то не прав, или просто кто-то не согласен с моим высказыванием... А петросянство - прочел, проржался, плюсанул.
                          Ответить
                    • В принципе, в Scala можно добиться очень интересных эффектов за счёт имплиситов. Стандартные коллекции могут возвращать различные типы результатов для одних и тех же операций. Пример: если bitSet.map( Int => Int) вернёт BitSet, а bitSet.map( Int => Double ) вернёт Set[Double].
                      Но достигнуто это такой архитектурой, по сравнению с которой код в топике - цветочки.
                      Впрочем, я пока не вижу пути, как применить имплиситы для достижения того-же эффекта.
                      Ответить
            • >Во время компиляции решить, какой итератор юзать исходя из типов ключа и значения... Да, слабо.
              Я это не вам. Просто тут
              > Красивый, понятный код, в духе KISS, не находите?
              некие Fai вспоминают "KISS (keep it simple, stupid — «не усложняй, тупица»)", мол типа можно сделать проще и тут же молчит, сосет и не делает проще.
              Ответить
            • Как-то так: R find(alias pred = "a == b", R, E)(R haystack, E needle)
              А в С++ да, даже стандартная библиотека выглядит как говно.
              Ответить
              • D?
                Ответить
              • >> Во время компиляции решить, какой итератор юзать исходя из типов ключа и значения
                > написал, как применить функцию поиска подмножества в контейнере с применением предиката
                к чему это?
                Ответить
                • >> kipar 3 часа назад # +1
                  >> Как-то так: R find(alias pred = "a == b", R, E)(R haystack, E needle)
                  >> А в С++ да, даже стандартная библиотека выглядит как говно.
                  > написал, как применить функцию поиска подмножества в контейнере с применением предиката

                  А где можно отсыпскачать исходники libastral, с помощью которого можно цитировать мысли собеседников, которых нет в постах?
                  Ответить
                  • ну оппонент явно предложил оптимальный вариант из его любимого языка, отвечающий на поставленную задачу - на этапе компиляции на основании условия из двух типов выбрать один
                    Ответить
                    • А, т.е. это не цитата, а просто объяснение приведенного кода. Я, к сожалению, D не знаю, поэтому мне сложно понять, что делает этот код.
                      Ответить
                      • http://dlang.org/phobos/std_algorithm.html#find

                        учитывая, что вышеприведенное им в одну строчку записывается через
                        boost::range::search(where, what, pred);
                        раз уж так не нравятся итераторы в
                        std::search(where.begin(), where.end(), what.begin(), what.end(), pred);
                        чем он хотел похвастаться, я даже в недоумении
                        Ответить
                        • Может поциент хотел сказать, что D может вызывать алгоритмы стандартной быдлотеки во время компиляции?
                          Ответить
                        • Только вот я привел сигнатуру этой функции, а используется-то она так: find("a=b+2")(where, what);
                          А в вашем boost\std как сигнатура search будет выглядеть?
                          Ага, как-то вот так: http://www.boost.org/doc/libs/1_50_0/libs/range/doc/html/range/reference/algorithms/non_mutating/search.html
                          Я даже не буду сюда копипастить этот ужас.
                          Ответить
                          • search(where, what, [](type a, type b) { return a==b+2; });

                            а в языке D равно это = или всё-таки ==?
                            Ответить
                            • ==, ошибся. Ну да, хоть лямбды ввели (хотя и менее лаконичные чем в D), без лямбд то совсем говно было. Но я повторяю, объявляется эта функция так:
                              template<class ForwardRange1, class ForwardRange2>
                              typename range_iterator<ForwardRange1>::type
                              search(ForwardRange1& rng1, const ForwardRange2& rng2);
                              
                              template<class ForwardRange1, class ForwardRange2>
                              typename range_iterator<const ForwardRange1>::type
                              search(const ForwardRange1& rng1, const ForwardRange2& rng2);
                              
                              template<
                                  class ForwardRange1,
                                  class ForwardRange2,
                                  class BinaryPredicate
                                  >
                              typename range_iterator<ForwardRange1>::type,
                              search(ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred);
                              ... десятки строчек с разными вариантами.

                              А в D - так как я привел. Ну и в теле компайл-тайм проверки на соответствие R, E и pred нужным типам.
                              Ответить
                              • > так как я привел
                                компилятор D, встречая незнакомое слово, считает это шаблонным параметром-типом?
                                Ответить
                                • первые скобки (pred = ..., R, E) - параметры времени компиляции, т.е. типы. вторые скобки - параметры времени исполнения. Так что компилятор понимает что R и E - типы соотв. haystack и needle.
                                  Ответить
                • Я и задачу то не понял за этим синтаксическим мусором. Если задача стоит - на этапе компиляции выбрать один из типов, то решается как-то так:
                  template INT(int i) {
                    static if (i == 32)
                      alias int INT;
                    else static if (i == 16)
                      alias short INT;
                    else
                      static assert(0); // not supported
                  }

                  Но зачем она для поиске в мапе я не понял.
                  Ответить
                  • ты хотел сказать
                    static if (__traits(isSame, key_type, value_type))
                        alias const_iterator iterator;
                    else
                        alias some_other_type iterator;

                    в с++ для этого тоже было предложение
                    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3329.pdf
                    не прижилось

                    поиск в мапе тут совсем не причем
                    приведен фрагмент из внутренней реализации std::set/std::map от MSVC - оба класса построены поверх внутреннего класса, реализующего к/ч дерево, и в какой то момент они, видимо, решают, как объявить итератор контейнера - как итератор этого внутреннего класса, или что-то более сложное
                    к вопросам чистоты синтаксиса - в редмонд
                    Ответить
                    • ага, я и забыл. const_iterator - очередное уродство С++. Мало того что иммутабельность кривая (нетранзитивная), так для нее еще и отдельный тип надо использовать.

                      А __traits(isSame, key_type, value_type) можно записать как
                      typeof(key_type) == typeof(value_type)
                      Ответить
                      • первые скобки (pred = ..., R, E) - параметры времени компиляции, т.е. типы. вторые скобки - параметры времени исполнения. Так что компилятор понимает что R и E - типы соотв. haystack и needle.
                        Ответить
                      • Извиняюсь, const_iterator в данном случае не причем, но это не отменяет претензий к крестам
                        Ответить
                      • >Мало того что иммутабельность кривая (нетранзитивная)
                        Что это значит и чем мешает?
                        Ответить
                        • В D если мы объявляем переменную immutable, это значит что она неизменяема и к ней, к примеру, можно без блокировок обращаться из разных потоков. А в С++ const ничего не гарантирует - насчет него вот: http://yosefk.com/c++fqa/const.html
                          Ответить
                          • А нахера вообще иммутабельность не сделали по умолчанию?
                            Ответить
                          • если ты в с++ объявишь нечто с const, но потом это нечто начинаешь менять (написав const_cast<>) - виноват, конечно, язык, он вынуждает тебя писать синхронизацию потоков на обращение к const объектам, ага
                            в языке с прямым доступом в память даже без const_cast всегда можно найти адрес чего-либо и насрать туда, только где тут здравый смысл?
                            Ответить
                            • Лень читать ссылку - основная претензия, грубо говоря, в том, что константный объект не защищён от записи на уровне железа, да?
                              Ответить
                              • Там вполне вменяемый FAQ, объясняющий чем является const, а чем не является. Почитай, возможно, почерпнешь что-то полезное.

                                > не защищён от записи на уровне железа
                                Да нет, не только. Еще претензия, что приходится дублировать код для итераторов и прочих псевдоуказателей.
                                Ответить
                                • На русском есть?
                                  Ответить
                                • Ах, обмануть меня не трудно!..
                                  Я сам обманываться рад!

                                  сколько можно обсужать это толстое трололо "вменяемый фак"
                                  Ответить
    • Метатернарные метаоператоры...
      Ответить

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