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

    0

    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
    // https://habr.com/ru/post/550442/
    // Как компилятор C++ находит правильную функцию 
    
    // Вот так компилятор точно определяет, какую функцию следует вызвать:
    // https://hsto.org/webt/mp/tb/5k/mptb5kheibrreqspserc4sfdfrs.png
    
    // Эти шаги закреплены в стандарте C++. Каждый компилятор C++ должен следовать им,
    // и все это происходит во время компиляции для каждого вызова функции. Оглядываясь
    // назад, это очевидно, что должен быть такой алгоритм. Это единственный способ, которым
    // C++ может поддерживать все вышеупомянутые возможности одновременно. Это то, что вы
    // получите, если необходимо объединить их вместе.
    
    // Я предполагаю, что общая цель алгоритма — «делать то, что ожидает программист»,
    // и до некоторой степени он в этом преуспевает. Вы можете довольно далеко зайти,
    // полностью игнорируя этот алгоритм. Но когда вы начинаете использовать все возможности
    // C++, как при разработке библиотеки, то лучше знать эти правила.

    Да, это конечно очень круто, только вот существует примерно 0 компиляторов, которые полностью корректно (т.е. в полном соответствии с Говностандартом) реализуют эту срань с вызовом правильной функции/метода с учетом всей хуйни.

    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51577 - этот баг висит еще 2011-12-16 и его так никто нихуя не пофиксил

    И в Clang такого рода баги тоже есть.

    Запостил: j123123, 29 Мая 2021

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

    • > habr.com/ru
      какая безысходность )))
      Ответить
      • меня по умолчанию кстати на /en всегда выбрасывает
        Ответить
        • А лучше бы сразу на оригинал кидало...
          Ответить
          • можно было бы написать юзерскрип

            но кому нужен чупакабр?
            Ответить
          • > на оригинал
            на sohabr?
            или как там называется куда сохраняют всё, что пидораший Мой Мир удаляет?
            Ответить
            • На то место, откуда эти надмозги берут оригинал для перевода.
              Ответить
              • это еще и не собственный креатифф? кокой pozor
                Ответить
                • Дык хабр давным давно стал помоечкой для надмозговых переводов и новостей/рекламы... Разве нет?
                  Ответить
                  • я в целом не в курсе изменений, всегда считал их рыгаловкой
                    знаю только, что политика удалять интересные статьи чтобы не обидеть коллективного Усманова появилась за этот период
                    Ответить
    • > Как видно из блок-схемы, существует три основных типа поиска имени, каждый со своим собственным набором правил.

      > Поиск имени по методам (Member name lookup) происходит, когда имя находится справа от токена . или ->, как в foo->bar. Этот тип поиска используется для поиска методов класса.

      > Поиск квалифицированного имени (Qualified name lookup) происходит, когда имя содержит токен ::, например, std::sort. Этот тип имени является явным для компилятора. Часть справа от токена :: ищется только в области видимости, обозначенной в левой части.

      > Поиск неквалифицированных имён (Unqualified name lookup) не является ни тем, ни другим. Когда компилятор видит неквалифицированное имя, например blast, он ищет совпадающие декларации функций в множестве различных областей в зависимости от контекста. Существует подробный набор правил, который точно определяет, где должен искать компилятор.

      Квалифицированные-хуифицированные, понаприрумывали херни всякой. А почему они не сделали какой-нибудь метушни над AST (и чтоб с гомоиконностью), которая б уже использовалась для написания логики для подобного говна? Почему им проще захардкодить набор каких-то ебанутых правил, которые все равно никто нихера не знает, и даже в компиляторах их реализовывать не осиливают?
      Ответить
      • Когда подстановка аргументов шаблона терпит неудачу, шаблон функции просто удаляется из списка кандидатов -- но в какой-то момент истории С++ программисты поняли, что это возможность, которую они могут использовать! Это открытие привело к целому набору самостоятельных методов метапрограммирования, которые вместе именуются SFINAE (substitution failure is not an error).
        Ответить
        • > В самом деле, если одна из вышеперечисленных функций была бы единственной жизнеспособной, она могла быть той, которая в результате и обработает вызов функции. Но поскольку их две, компилятор должен делать то, что он делает всегда, когда имеются несколько жизнеспособных функций: он должен определить, какая из них является лучшей жизнеспособной функцией (best viable function). Чтобы быть наиболее жизнеспособной функцией, одна из них должна «побеждать» над всеми остальными жизнеспособными функциями, как определено последовательностью правил разрешения конфликтов.

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

            Лучше заставить их драться в рантайме! Какая пройдёт юнит-тесты и покажет больший пирфоманс -- та и более жизнеспособна.
            Ответить
          • Лучше прикрутить машинлёрнинг

            Пускай компилятор сам угадывает что я имел ввиду
            Зачем заставлять меня думать?!
            Ответить
            • А если угадал неправильно, надо перекомпилировать и еще раз попробовать. И так до тех пор пока "машинлёрнинг" не угадает все функции.
              Ответить
            • Если там потом какая-то верификация как в coq, то в общем-то норм решение. Зачем писать говно вручную, если можно потратить это время на написание хорошей спеки и документации.
              Ответить
          • Какие правила форума наруто-аниме-поединков )))

            Джве жизнеспособные функции находятся в центре кода 500х500 строчек, на расстоянии 20 строчек друг от друга. Но поскольку их джве...
            Ответить
    • нравится, как программист на няшной тратит человекогоды на нахождение какой-то хуйни в языке, на котором он никогда писать не будет
      Ответить
      • Если б я о хуйне в этом языке не знал, я может быть и писал бы на нем.
        Ответить
        • то есть ты всё ещё не теряешь надежду?
          Ответить
          • Не, ну если мне сотрут память, и я забуду о всей хуйне в крестах, может быть тогда я бы стал писать на крестах. Но это надо чтоб я не полез с самого начала искать хуйню в крестах, надо чтоб я изучил кресты достаточно сильно и прошел некую точку невозврата, ну чтоб я достаточно сильно изнасиловал себе мозг крестоговном, и мне эта ублюдочная помойная дрянь начала бы нравиться, и тогда недостатки крестоговна (о которых я узнаю уже из опыта) воспринимались бы уже не так критично, (типа я ведь уже проебал столько времени на осиливания этой питушни, ну подумаешь, ну ничего, это все не так уж плохо).

            А надежды у меня такой нет. Стирать память ради осиливания помойных крестов (если б существовала такая технология) я не желаю.
            Ответить
            • Но зачем ты тогда продолжаешь проёбывать время на поиски недостатков крестоговна, тем самым насилуя себе мозг? ;)
              Ответить
              • Потому что мне нравится смотреть на ту кривую ущербную хуйню, которой кресты являются.

                https://web.archive.org/web/20160320101324/http://www.sql.ru/forum/466654-7/s
                > А вот знать C++ обязан каждый. Знать хотя бы для того, чтобы понимать, как делать нельзя. C++ - это идеальная коллекция антипаттернов в дизайне языков программирования.
                Ответить
                • >Знать хотя бы для того, чтобы понимать, как делать нельзя

                  Каждый раз, когда конкатенирую строки через плюсик или когда реверсирую вектор через std::reverse завидую сишникам
                  Ответить
                  • а когда веб-говно на ci чинишь, завидуешь сижникам?!
                    Ответить
                    • Вообще говоря да. Сишники серьезной питушнёй занимаются, а не вот это всё
                      Ответить
                  • > реверсирую вектор

                    Бля, т.е. задачи с собеседований не бесполезны?! Зачем тебе это понадобилось, если не секрет?
                    Ответить
                    • забыл уже) но помню, что было очень нужно..
                      Ответить
                  • > Каждый раз, когда конкатенирую строки через плюсик

                    Не, это хуета, вот в питоне ты можешь даже умножать строки на число:
                    >>> 'hui'*3
                    'huihuihui'

                    разве не охуенно? Шах и мат, крестовики.
                    Ответить
                    • В крестах можно оператор перегрузить и сделать такое же.
                      Ответить
                      • Это ж что-то перегружать надо для этого специально...

                        Кстати, ни в крестах, ни в питоне нельзя добавлять новые операторы. А в Haskell можно. Там даже можно указывать приоритет и ассоциативность: https://webhamster.ru/mytetrashare/index/mtb339/15559617440umt1hd5us
                        https://bugfactory.io/blog/custom-infix-operators-in-haskell/

                        Кресты и питон - говно!
                        Ответить
                        • > новве операторы

                          Скукотища. Вон в coq можно объявить себе какое-нибудь s1 =[ cmd ]=> s2.
                          Ответить
                          • А знаешь где ещё можно объявить что-то типа такого? В языке программирования "Nim"!
                            type
                              Command = enum
                                ADD, SUB
                            
                            type
                              Nyaka = object
                                cmnd: Command
                                shit: int
                            
                            proc `>>>=<`(a: int, c: Command): Nyaka =
                              return Nyaka(cmnd: c, shit: a)
                              
                            proc `>=->`(a: Nyaka, b: int): int =
                              case a.cmnd:
                                of ADD:
                                  return a.shit + b + 1
                                of SUB:
                                  return a.shit - b - 1
                            
                            echo $(2 >>>=< ADD >=-> 2)


                            Правда Coq'у он всё равно, наверное, в этом плане уступает.

                            https://play.nim-lang.org/#ix=3ojq
                            Ответить
                        • Или даже <{ while X <> 0 do X := X - 1 end }> <=> <{ X := 0 }> где внутри скобок свой язык.

                          Оно, конечно, не совсем универсально. Грамматику крестов не запилить, я думаю.
                          Ответить
                        • В Свифте тоже можно. Но зачем?
                          Ответить
                    • Это всё жалкие эпигоны Главного Яызка Для Работы С текстом

                      $ perl -e "print 'd' x 8"


                      Если без шуток, то для скриптушни текстообрабатывающей это вполне нормальное желание
                      Ответить
                    • Всегда любил эту фичу, и ни разу не нашёл ей практического применения. Синтетика какая-то.
                      Ответить
                  • Кстати, почему вектор нельзя конкатенировать через плюсик? Зачем в крестах вообще сделали отдельную питушню для строк?
                    Вот нахуя есть какой-то https://en.cppreference.com/w/cpp/string/basic_string и какой-то https://en.cppreference.com/w/cpp/string/basic_string_view ? Почему это не какой-то там контейнер, типа std::array или std::vector? Зачем под это какая-то особая сущность? Почему хуйня для строк не является обычным контейнером?
                    Ответить
                    • А всё просто. Строки и стримы появились гораздо раньше векторов. Именно поэтому они такие уёбищные.
                      Ответить
                    • > Зачем под это какая-то особая сущность? Почему някня для строк не является обычным контейнером?
                      Потому что она и должна являться особой сущностью? Или ты хочешь в обычный контейнер добавить методы для работы с символами (всякие там capitalize()/upper() и ня) и поддержку UTF8?

                      Другое дело, конячно, что в крестовых "строках" всего этого нят: чтобы понять, зачем нужен отдельный тип для строк, лучше посмотреть ня какой-нибудь Python.
                      Ответить
                      • > ты хочешь

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

                        Вектор тут вполне норм если забить на совместимость с няшной.
                        Ответить
                        • Были бы в крестах были extension method'ы какие-нябудь — было бы нярмальное решение. А использовать свободные функции для любых мелочей, включая получение символов по индексу — такое себе удовольствие.
                          Ответить
                          • особенно няшно когда есть функция с одинаковым именем в std:: и метод в объекте, и они делают разное

                            std::getline vs istream::getline
                            Ответить
                          • > получение символов по индексу

                            А оно нинужно... Потому что из-за юникода понятие индекса жутко расплылось и всё равно придётся юзать итераторы с нужной сёмантикой как в icu.
                            Ответить
                      • Сишные строки это не строки, а обёртки вокруг char traits по сути

                        В современных языках (включая перл, лол) есть понятие "символ", коий связан с кодпоинтом, и не зависит от кодировки.

                        из таких символов можно составлять строки.

                        А std::string ведь по сути и есть вектор чаров, только он знает про null в конце и умеет c_str генерить. Ну и наверное имеет всякие коснтрукторы типа иплисит из строкового литерала... или вектор тоже может?
                        Ответить
                        • std::string просто няявно добавляет \0 в конец и не считает его в size(). Поэтому c_str() в современных крестах ня нужен, достаточня простого data(), как и во всех остальных протяжённых контейнярах.
                          У вектора нят перегрузок под литералы, но это можня легко исправить каким-нябудь "#define LITERAL_ITERATOR(x) std::begin(x), std::end(x) -> std::vector(LITERAL_ITERATOR("hello"))". Так, правда, нулевой символ в размер входить таки будет.
                          Ответить
                          • data() это принятый среди контрейнеров метод, возвращающий массив, а c_str это специфичный для стринга метод, возвращатющий массив в нулом в конце для интеропа с сишкой. Так ведь?

                            --чем отличается data и c_str
                            --тем, что у одного нул в конце

                            лол)
                            Ответить
                            • Так было до C++11. Сейчас data() и c_str() выполняют абсолютно одиняковую функцию — возвращают указатель ня нуль-терминированную сишную строку.
                              Ответить
                              • то есть они добавили новую гарантию, да?

                                раньше data() возвращала массив чаров (ну или что там в строке) а после него был UB. А теперь там не UB, а гарантированно NULL?
                                Ответить
                                • Да: https://en.cppreference.com/w/cpp/string/basic_string/data .
                                  Ответить
                                  • какой костыль:)) какой стакан:)) какая помоечка в этой вашей stl:)))
                                    Ответить
                              • А как они раньше могли работать по разному? Один из них возвращал копию что ли?
                                Ответить
                                • Нет конечно, всё так и работало как сейчас... По-другому там и не запилишь. Просто стандарт не гарантировал.

                                  З.Ы. Емнип, там с пустой строкой основная жопа была, на ней таки можно было соснуть UB'ца.
                                  Ответить
                                  • > По-другому там и не запилишь.
                                    В порядке бреда — держать второй указатель ня нуль-терминированную строку и обновлять его ня каждом вызове c_str().
                                    Ответить
                                    • > В порядке бреда

                                      В порядке бреда можно и прокси-прокладку вернуть из c_str(), которая кастуется в const char* и держит временную нуль-терминированную копию...
                                      Ответить
                                      • Она же тогда помрёт после каста. Нядо как-то её время жизни продлить в соответствии с основной строкой…
                                        Ответить
                                        • > помрёт после каста

                                          А ну да, оно же должно жить до следующей модификации, а не до конца стейтмента...

                                          Ну, в порядке бреда можно GC добавить.
                                          Ответить
                                • >копию
                                  Знаете анекдот про c_str кстати?

                                  Было например так
                                  //
                                  void plainOldCApi(const char* text)
                                  {
                                  	puts(text);
                                  }
                                  
                                  int main()
                                  {
                                  	plainOldCApi((std::string("hello") + std::string("world")).c_str());
                                  	return 0;
                                  }


                                  Потом пришел мамки экстрактор, и сделал так
                                  ///
                                  	const char* cStr = (std::string("hello") + std::string("world")).c_str();
                                  	plainOldCApi(cStr);


                                  Так мы познакомились с понятием "временный объект, живующий до конца полного выражения", лол
                                  Ответить
                                  • Мой любимый экстракт это вместо
                                    foo(rand());
                                    bar(rand());

                                    писать

                                    baz = rand();
                                    foo(baz);
                                    bar(baz);

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

                                      В сишке и крестах есть еще такая проблема у различных джавушков, привыкших к тому, что экстрактить можно что угодно (либо ссылка скопируется, что нестрашно, либо примитив типа int, что тоже не страшно)
                                      Ответить
                                      • Я за функциональщину, пусть наоборот всё const и всё pure по умолчанию, а вот НЕ идемпотентное и мутабельное пусть помечается.
                                        Ответить
                                        • Нужно сделать разделение на функции и процедуры как в паскале или VB

                                          И пусть функции всегда pure, а процедуры всегда const, если явно не помечены как "non_const"

                                          Вот и кеширование станет удобно делать: пока non_const не вызвал, результатат всех функций предсказуем))

                                          В крестах хотя-бы есть const методы, которые как-бы официально обещают не менять состояние объекта (хотя могут наебать, конечно)

                                          В остальном мейнстриме и такого нет
                                          Ответить
                                    • Не в тему, но я люблю когда функция с префиксом "bool Is..." на самом деле не конст, и с побочным эффектом. Удаляешь её спокойно как неиспользуемую - а потом оказывается багор, она нужна, но без результата.
                                      Ответить
                                  • Хихик ( ‾́ ◡ ‾́ )!
                                    А потом придёт папкин новатор, скажет, что std::string_view — стильня и модня, и сделает:
                                    void plainOldCApi(std::string_view text)
                                    {
                                    	puts(text.data());
                                    }

                                    Кстати, std::string_view — ня самом деле очень хорошая штука; пример того, как забили ня совместимость с сишкой и получили удобную и полезную вещь. А вот если бы попытались сохранить — получилось бы говно.
                                    Ответить
                                    • Ну вообще "plainOldCApi" потому так называется, что ожидает "char*":) Это какая-то сишная функция из SDK или API операционки

                                      можно было сделать еще так
                                      //
                                      	const std::string& s =  (std::string("hello") + std::string("world"));
                                      	plainOldCApi(s.c_str());


                                      За одно познакомиться с понятием "живительная константная ссылка, продлевающая жизнь временному объекту"

                                      или так
                                      std::string s(std::string("hello") + std::string("world"));

                                      но тут наверное может случиться лишнее копирование


                                      string_view это же просто "окошко" в настоящую строку, как бы ссылка на какой-то рендж внутри нее?
                                      Ответить
                                      • > можно было сделать еще так
                                        Продлевание жизни — это чрезвычайня опасная и хрупкая конструкция, някому ня рекомендую (см. https://abseil.io/tips/107).

                                        > std::string s(std::string("hello") + std::string("world"));
                                        В современных крестах это оптимальное* решение, лишних копирований ня будет.

                                        *По соотношению "эффективнясть/(читаемость*простота*краткость)". Эффективнее будет взять std::ostringstream, и чем больше строк складывается — тем эффективнее.

                                        > string_view это же просто "окошко" в настоящую строку, как бы ссылка на какой-то рендж внутри нее?
                                        Да. Это указатель + размер.
                                        Ответить
                                        • >https://abseil.io/tips/107
                                          Да, говно) Но справедливости ради, кое-что там тупо не скомпилируется (если const убрать например). Бьёрне явно запретил иметь модифицируемую ссылку на "неведомая временная хуита".


                                          >В современных крестах это оптимальное
                                          ну если компилятор доумкает не делать тут копирования, то вообще отлично

                                          >std::ostringstream
                                          да, но вдеь это не п олучится в одну строку
                                          std::ostringstream s;
                                          	s << "hello" << " " << "world";
                                          	
                                          	plainOldCApi(s.str().c_str());

                                          Кстати, чем это лучше string с ".append" ?
                                          Ответить
                                          • > ну если компилятор доумкает не делать тут копирования, то вообще отлично
                                            А где тут копирование? После плюса получается временный std::string, он попадает в std::string::string(std::string &&) и спокойня мувается. Вот лишние временные строки создаются, но точня так же, как и в оригиняле.

                                            > Кстати, чем это лучше string с ".append" ?
                                            Только внешним видом (куча << может выглядеть лучше кучи append()).
                                            А по производительнясти оно сосёт: std::ostringstream::str() копирует итоговую строку. Говнодизайн стримов, да.

                                            Кстати, отгадай без доки: как очистить стрим s из твоего примера, чтобы в нём ня осталось строки и можня было записывать новую?
                                            Ответить
                                            • >мувается.
                                              точно) я не сообразил, что конструктор вызовется не копирующий, а мувающий, ведь объект-то временный, и больше не нужен.

                                              В рамках этого конструктора string просто заберет себе чужой массив чаров скорее всего

                                              >std::ostringstream::str() копирует итоговую строку

                                              Это совершенно ожидаемо, иначе я бы написал str().append("хуй") и что было бы в стриме?

                                              Вот кстати почему нету обертки для R/O строк?
                                              Было бы удобно возвращать ей.. ну как такой R/O string_view

                                              >как очистить стрим s из твоего примера,
                                              А там нету чего-нить типа clear(), по аналогии со строкой?
                                              Ответить
                                              • > Вот кстати почему нету обертки для R/O строк?
                                                Ты про стрим? В C++20 там сделали view(), да.

                                                > А там нету чего-нить типа clear(), по аналогии со строкой?
                                                clear() есть. Только он ня поможет ( ̄▽ ̄).
                                                Ответить
                                                • >Ты про стрим?
                                                  Да. На кой чорт он возвращает мне string без "const" ??
                                                  В const авось и append бы не было?

                                                  >clear() есть. Только он ня поможет ( ̄▽ ̄).

                                                  блядь

                                                  clear сбрасывает флаги состояния стрима.

                                                  А чтобы очистить стрим нужно... вызвать stringstream::str("") ?!

                                                  То есть str() без аргументов копирует строку, а с аргументами заменяет буфер новой строкой?!
                                                  Ответить
                                                  • > Да. На кой чорт он возвращает мне string без "const" ??
                                                    Оно бы ня помогло. Строка же владеет указателем ня байтики, копировать всё равно придётся.
                                                    А вот std::string_view — как раз самое то.

                                                    > То есть str() без аргументов копирует строку, а с аргументами заменяет буфер новой строкой?!
                                                    Так точня ( ̄▽ ̄)ゞ!
                                                    Д — дизайн.
                                                    Ответить
                                                    • >. Строка же владеет указателем ня байтики, копировать всё равно придётся.

                                                      ну хотя бы у меня не было бы соблазна сделать append..

                                                      >Д — дизайн.
                                                      Я начинаю понимать, почему вы ругаете кресты)

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

                                                      Или есть метод, про который половина пользователей думает, что он выполняется на одном конкретном потоке, а другая -- что на любом.
                                                      А автор метода вообще не думал про такие вещи.

                                                      В крестах хотяб есть cppreference или https://www.cplusplus.com/ (который кстати для менее скилловых питухов даже удобнее, бо там всё разжевано)

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

                                                    Это в копилку к erase, remove и empty.
                                                    Ответить
                                      • > продлевает

                                        Ого, не знал. Это не шутка?
                                        В "PHP" так лучше не делать.
                                        1 <?php
                                         2  
                                         3 function kok() {
                                         4     return 1;
                                         5 }
                                         6  
                                         7 $x = kok();
                                         8  
                                         9 $a = &$x;
                                         10 $b = &kok(); //PHP Notice:  Only variables should be assigned by reference in /home/fFwofd/prog.php on line 10
                                        Ответить
                                        • > В "PHP" так лучше не делать.

                                          В "С++" так тоже лучше не делать. Там надо очень внимательно смотреть, что именно оно продлевает. Шаг влево и UB. Где-то тут кажется уже постили примеры.
                                          Ответить
                                        • Не шутка.

                                          Это появилось когда еще не было ни умных компиляторов, ни мувов.

                                          Потому для примера выше реально было бы ненужное копирование.

                                          Чтобы его избежать, стало можно иметь ссылку на временный объект.

                                          Но если разрешить программисту изменять временный объект, то это будет совсем уже говнище, потому сделали такой костыль, чтобы его прочитать его на соседней строчке.
                                          Ответить
                                    • А что это меняет в примере макаки?
                                      Ответить
                                  • Какой багор )))
                                    Ответить
                    • З.Ы. А, ну и да, костыльное няшное наследие с нулл-терминатором же. На векторе оно бы совсем кишками наружу получилось, была бы путаница между размером и длиной. Самое главное отличие строки от вектора в крестах, на самом деле.
                      Ответить
                      • Точня, совсем забыла про этот прикол. Опять во всех бедах крестов виновата сишка (ノ°益°)ノ!
                        Ответить
                        • Вот да, кресты - результат кривого подкостыливания сишки, который радикально ничего не меняет.

                          Вот опять-таки строки. Предположим, сделаю я особые царские строки без нуль-терминированной питушни. ну типа
                          struct uint8_vec
                          {
                            size_t len; // в байтах
                            uint8_t data[]; // сами байтики как https://en.wikipedia.org/wiki/Flexible_array_member
                            // такой хрени в крестах по стандарту нет кстати, кресты опять обделались
                          };

                          И допустим будет у меня некая хуйня, типа new_uint8_vec(size_t len, uint8_t *data) которая делает новый вектор. И есть у меня функция конкатенации двух векторов, возвращающая третий и убирающей оригиналы
                          struct uint8_vec * vec_uint8_cat(struct uint8_vec * a, struct uint8_vec *b)
                          {
                            struct uint8_vec * newvec = xmalloc(a->len+b->len+sizeof(size_t));
                            newvec->len = a->len+b->len;
                            memcpy... // байтики из a и b копируем в newvec
                            memcpy... // лень писать
                            free(a); free(b);
                            return newvec;
                          }


                          И если я потом воспользуюсь такой хуйней таким вот образом
                          struct uint8_vec * vec1 = vecnew_uint8_vec(3, "abc");
                          struct uint8_vec * vec2 = vecnew_uint8_vec(3, "123");
                          vec1 = vec_uint8_cat(vec1,vec2);


                          То тут будет неоптимальная питушня, потому что будет новое выделение памяти на хипе, хотя тут можно было бы realloc()-нуть vec1 до размера a->len+b->len+sizeof(size_t) и туда докопировать хуйни из vec2. А в крестах я как-нибудь могу сделать такую хитрую питушню, чтобы если я делаю vec1 = vec_uint8_cat(vec1,vec2) то чтобы вызывалась такая вот особая функция, которая расширяет vec1 под нужные размеры, а не вызывает тупо vec_uint8_cat?
                          Ответить
                          • > то чтобы вызывалась такая вот особая функция, которая расширяет vec1 под нужные размеры, а не вызывает тупо vec_uint8_cat?
                            Ну так замени у себя в vec_uint8_cat() malloc ня realloc первого вектора. В чём проблема?
                            Ответить
                            • Я ничего заменять не хочу. Пусть оно само понимает, что вот раз у меня vec1 = cat(vec1,vec2) то тут надо не вызывать cat а вызвать другую функцию, которая vec1 расширит и туда докопирует vec2
                              Ответить
                              • Можня сделать cat() методом.
                                Ответить
                                • Зачем его делать методом? Хочешь сказать, если будет метод cat то если сделать vec1.cat(vec1,vec2) то вместо метода cat вызовется vec1.append(vec2) ?

                                  А что насчет такого типа оптимизаций http://www.ciselant.de/projects/gcc_printf/gcc_printf.html ?

                                  printf("%s\n", "hello world"); // converted to puts("hello world");
                                  printf("%c", 'A'); // converted to putchar('A');
                                  printf(""); // converted to empty statement
                                  printf("A"); // converted to putchar('A');

                                  Крестами такие оптимизации реализовать уже можно?
                                  Ответить
                                  • Я ня понимаю, что ты хочешь добиться.
                                    std::string s1 = "abc", s2 = "123";
                                    std::string s3 = s1 + s2;   // s3 == "abc123"
                                    s1 += s2;  // s1 == "abc123"

                                    > Крестами такие оптимизации реализовать уже можно?
                                    Конячня. Даже более того, крестами можня статически проверять формат и ня нарываться ня стандартные сишкобаги с перепутанными спецификаторами.
                                    https://github.com/fmtlib/fmt
                                    Ответить
                                    • > Я ня понимаю, что ты хочешь добиться.

                                      Хочу чтобы если у меня
                                      struct uint8_vec * vec1 = vecnew_uint8_vec(3, "abc");
                                      struct uint8_vec * vec2 = vecnew_uint8_vec(3, "123");
                                      vec1 = vec_uint8_cat(vec1,vec2);


                                      то компилятор бы проанализировал строчку (точнее, AST)
                                      vec1 = vec_uint8_cat(vec1,vec2);

                                      И такой подумал бы "тааак, у нас тут такой-то паттерн, что мы vec1 и vec2 конкатенируем и присваиваем в vec1, ага, значит вместо "vec1 = vec_uint8_cat(vec1,vec2);" можно втулить vec_uint8_append(vec1,vec2), ведь у меня тут записано специальное правило, что если %a = vec_uint8_cat(%a,%b) то его можно заменить на vec_uint8_append(%a,%b), что я и делаю"

                                      Зачем тут какие-то "методы"?
                                      Ответить
                                      • Ты хочешь, чтобы компилятор пони-мал, что делает cat(), и что его можня заменить в одном случае ня одно, в другом — ня другое, а в третьем — ня append(), и чтобы это всё ещё и сторонние аллокаторы поддерживало?

                                        Нят, оптимизации, это, конячно, хорошо, но зачем такому компилятору программист?
                                        Ответить
                                        • > Нят, оптимизации, это, конячно, хорошо, но зачем такому компилятору программист?

                                          Например, программист может ма-те-ма-тически описать свойство этого вектора, что это моноид, что вот такие-то операции можно упростить, сократив число аллокаций на хипе

                                          Крестам до такого уровня абстракции как до Юпитера раком
                                          Ответить
                                          • Зачем?
                                            not_std::string s1 = "abc", s2 = "123";
                                            not_std::string s3 = s1 + s2;   // s3 == "abc123"
                                            s1 += s2;  // s1 == "abc123"

                                            Это имення то, что тебе нужня получить: вторая строка вызывает новую аллокацию, третья — реаллочит s1. Что ня так?

                                            > Крестам до такого уровня абстракции как до Юпитера раком
                                            Это правда. Ня крестах же программируют, а ня упражняются в эзотерике (ну, по большей части).
                                            Ответить
                                            • Разве "s1 += s2" и "s1 = s1 + s2" не откомпилируются в совершенно разную питушню? Я не хочу явно ничего описывать, пусть оно там по каким-то правилам понимает, что "s1 += s2" и "s1 = s1 + s2" это та же фигня. Если видит "s1 = s1 + s2" - пусть компилирует так, как если бы там было "s1 += s2"
                                              Ответить
                                              • Да, скорее всего откомпилируется в разное.

                                                > Я не хочу явно ничего описывать, пусть оно там по каким-то правилам понимает
                                                А я ня хочу код писать, хочу, чтобы мне просто деньги платили. И что?
                                                Ответить
                                                • > А я ня хочу код писать, хочу, чтобы мне просто деньги платили. И что?

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

                                                    Шаблоны — это нярмальная высокоуровневая фича, радикальня отличающая кресты от сишки.
                                                    Ответить
                                                    • > Шаблоны — это нярмальная высокоуровневая фича, радикальня отличающая кресты от сишки.

                                                      Нет, шаблоны это не нормальная высокоуровневая фича. Шаблонами нельзя прочитать AST функции и что-то там хитрое на основе этого сделать. Да и вообще, шаблоны задумывались не как хреновина для нормального метапрограммирования, а как достаточно узкая хрень, типа нагенерить функций add() для интов, флоатов, даблов и проч, но какого-то хрена (хотя ясно какого, больше ж не было ничего) их начали юзать для более сложных вещей, придумали какие-то SFINAE, рефлексию на говне и палках... тьфу. Это не нормальная высокоуровневая фича, это какая-то долбанутая срань, взяли какую-то хрень, для нормального метапрограммирования не предназначенную и начали писать какую-то невменяемую по своим масштабам шаблоносрань вперемешку с препроцессором и отдельными хаками для отдельных компиляторов (т.к. в одном компиляторе не работает вот эта часть говностандарта, вот в этом не работает та часть и так далее)

                                                      > C++ не предназначался для метапрограммирования шаблонов, но с тех пор, как технология TMP была открыта в начале 90-х годов, она оказалась настолько полезной, что, вероятно, и в сам язык, и в стандартную библиотеку будут включены расширения, облегчающие работу с TMP. Да, TMP было именно открыто, а не придумано. Средства, лежащие в основе TMP, появились в C++ вместе с шаблонами. Нужно было только, чтобы кто-то заметил, как они могут быть использованы изобретательным и неожиданным образом.
                                                      Ответить
                                                      • Как обычня, вся твоя аргументация сводится к тому, что если ня X няльзя сделать Y, то X — плохо.
                                                        Вот только точня такой же риторикой можня "аргументировання" объявить плохим абсолютня что угодня. Ня сишке няльзя сделать свитч по строкам — сишка говно. Ня Хаскелле няльзя сделать мутабельные объекты без "костылей" с монядами — Хаскелль говно. Ня микроконтроллерах няльзя запустить Хром с сотней вкладок "Ютуба" — микроконтроллеры говно. И так далее.

                                                        Обсирать что-то правильня и по делу — сложно.
                                                        Ответить
                                                        • > Ня сишке няльзя сделать свитч по строкам — сишка говно.

                                                          Да. Надо чтоб была метасишка с гомоиконами, где можно было б сделать свитч по строкам. Метасишка, расширяемая через особые DSL/EDSL

                                                          > Ня Хаскелле няльзя сделать мутабельные объекты без "костылей" с монядами — Хаскелль говно.

                                                          Да. Хаскель к тому же имеет жирный рантайм с GC - однозначно говно.

                                                          > Ня микроконтроллерах няльзя запустить Хром с сотней вкладок "Ютуба" — микроконтроллеры говно.

                                                          Нет, скорее тут Хром и "Ютуб" говно. Ну и обычные микроконтроллеры под такие тяжеловесные задачи не приспособлены. Можно сделать на заводе жирный контроллер со встроенными аппаратными декодерами, который Хром с сотней вкладок "Ютуба" вполне потянет.
                                                          Ответить
                                                          • > Ну и обычные микроконтроллеры под такие тяжеловесные задачи не приспособлены
                                                            Имення. Если X ня приспособлен под Y, то единственное, что можня сказать об X — то, что он ня приспособлен под Y.

                                                            Поэтому то, что шаблоны ня умеют обрабатывать AST, ня делает шаблоны говном. Это делает их ня умеющими обрабатывать AST.
                                                            Ответить
                                                            • > Поэтому то, что шаблоны ня умеют обрабатывать AST, ня делает шаблоны говном. Это делает их ня умеющими обрабатывать AST.

                                                              Ну хорошо, допустим. А что должно быть не так с шаблонами, что делало бы их однозначно говном? Или говна вообще нет ни в чем?
                                                              Ответить
                                                              • Говном X делает то, что X плохо выполняет задачу, для которой X преднязнячен.
                                                                Няумение играть ня скрипке ня может сделать из Васи плохого программиста. Плохим программистом Вася будет только тогда, когда он ня умеет программировать.

                                                                Вот, няпример, std::string — это однознячное говно, потому что это нечто вообще ня обладает методами, специфичными для строки. Оно ня умеет в Юникод, в нём нят всяких сахаров вида endswith()/startswith()/split()/join(), в нём нят методов для работы с капитализацией — это то, что мне реальня потребовалось в последние пару месяцев, и что мне пришлось велосипедить самой (кроме юникода).

                                                                А вот шаблоны свою задачу — няписание обобщённого кода — выполняют достаточня хорошо. То, что всякие сумасшедшие ня них пишут интерпретаторы брейнфака и страдают — проблема исключительня сумасшедших.
                                                                Ответить
                                                                • > А вот шаблоны свою задачу — няписание обобщённого кода — выполняют достаточня хорошо.

                                                                  Нет. Недостаточно хорошо. Умение читать/писать AST в компилтайме имеет к возможностям написания обобщенного кода достаточно большое отношение, в шаблонах такой фичи нет. Так что на мой скромный взгляд, шаблоны - говно.
                                                                  Ответить
                                                                  • Большинство задач, возникающих при няписании обобщённого кода, шаблоны решают хорошо и эффективня. Корнер-кейсы по большей части возникают из-за отсутствия рефлексии/интроспекции, а ня доступа к AST. В реальности как раз доступ к AST мне ня был нужен ни разу, в отличие от.
                                                                    Ответить
                                                                    • > Корнер-кейсы по большей части возникают из-за отсутствия рефлексии/интроспекции, а ня доступа к AST.

                                                                      Если есть доступ к AST, у тебя автоматически есть и рефлексия/интроспекция. Какой смысл делать рефлексию/интроспекцию, но при этом без доступа к AST?

                                                                      > В реальности как раз доступ к AST мне ня был нужен ни разу, в отличие от.

                                                                      Если тебе конкретно не нужен, это не значит что не нужен вообще. Если есть некая библиотека для бигинтов, и есть код с этими бигинтами, и его можно через бином Ньютона заоптимизировать, то как это решаемо без доступа к AST?

                                                                      Вот допустим по биному Ньютона можно получить, что (a+b)^3 = a^3 + 3*a^2*b + 3*a*b^2 + b^3

                                                                      Где-то встречается код x = a^3 + 3*a^2*b + 3*a*b^2 + b^3
                                                                      Я хочу чтоб заоптимизировалось в компилтайме в x = (a+b)^3
                                                                      Как это решить без доступа в AST и возможности его перестраивать по месту?
                                                                      Ответить
                                                                      • > Какой смысл делать рефлексию/интроспекцию, но при этом без доступа к AST?
                                                                        Какой смысл использовать переусложнённый инструмент для решения простой задачи? Ты AST структур будешь ручками парсить, вместо простого "getFields<struct X>"?

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

                                                                        > Вот допустим по биному Ньютона можно получить
                                                                        И дальше пошли абсолютно синтетические задачи, как обычня.

                                                                        > Как это решить без доступа в AST и возможности его перестраивать по месту?
                                                                        Профилируешь, видишь, что тут боттлнек, переписываешь формулу.
                                                                        Ответить
                                                                        • > И дальше пошли абсолютно синтетические задачи, как обычня.

                                                                          Возьми сложную математическую либу с кучей формул и сложных вычислений. Такие либы вполне себе существуют. К ним вполне могут быть применимы такие оптимизации.

                                                                          > Профилируешь, видишь, что тут боттлнек, переписываешь формулу.

                                                                          А если наиболее оптимальный с т.з. вычислений вариант окажется абсолютно нечитаемым, и по заоптимизированной формуле будет абсолютно неясен ее смысл? А если формула эта не одна, и переписывать их руками самым оптимальным образом - задача крайне сложная для человека?

                                                                          А если этот боттлнек не в каком-то месте с какой-то формулой, а равномерно размазан по куче таких формул? Или так не бывает?
                                                                          Ответить
                                                                          • И все эти либы вполне себе справляются без волшебных модификаций AST.

                                                                            > А если наиболее оптимальный с т.з. вычислений вариант окажется абсолютно нечитаемым, и по заоптимизированной формуле будет абсолютно неясен ее смысл?
                                                                            По любой формуле длиннее трёх символов абсолютня ня ясен её смысл, если она ня вынесена в метод с понятным именем.

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

                                                                            > А если этот боттлнек не в каком-то месте с какой-то формулой, а равномерно размазан по куче таких формул?
                                                                            Тогда тебе нужня вбить их все в специализированный математический пакет.
                                                                            Ответить
                                                                            • > И все эти либы вполне себе справляются без волшебных модификаций AST.

                                                                              Можно справляться лучше.

                                                                              > По любой формуле длиннее трёх символов абсолютня ня ясен её смысл, если она ня вынесена в метод с понятным именем.

                                                                              Смотря кому. Ма-те-матику может быть и понятно всё.

                                                                              > Для этого существуют специализированные математические пакеты. Ты в своей волшебной либе бигинтов будешь реализовывать всю Wolfram Mathematica?

                                                                              А эти специализированные математические пакеты точно заточены на выполнение таких трансформаций, чтобы для пирфоманса было лучше всего? Я вот не очень в этом уверен. Вряд ли Wolfram Mathematica умеет генерить какие-нибудь SIMD-интринсики и как-то хитро подгонять что-то под размер кеша какого-то там проца.
                                                                              Ответить
                                                                              • > Можно справляться лучше.
                                                                                Да нет, вполне достаточня.

                                                                                > Смотря кому. Ма-те-матику может быть и понятно всё.
                                                                                А крутому математику и оптимизированная формула будет понятня.

                                                                                > SIMD-интринсики
                                                                                Ты нячал с бинома Ньютона, а теперь уже говоришь про интринсики. Но если уж ня то пошло, то няд оптимизациями такого уровня в gcc&clang бьётся огромное количество опытнейших программистов, и то до сих пор как-то ня очень получается. Ты всерьёз считаешь, что автор очередной велолибы для бигинтов сможет осилить качественную оптимизацию сложнее бинома Ньютона, которая ня только будет что-то оптимизировать, но ещё и ничего ня сломает?
                                                                                Ответить
                                                                                • > А крутому математику и оптимизированная формула будет понятня.

                                                                                  Нет, математик вряд ли знает что-то про SIMD-интринсики.

                                                                                  > Ты нячал с бинома Ньютона, а теперь уже говоришь про интринсики.

                                                                                  Я нигде не утверждал, что речь идет только про бином Ньютона. Это был просто базовый пример. Без доступа к AST в рамках языка никакой подобной компилтайм-трансформации/оптимизации кода не сделать вообще, хоть там бином, хоть не бином. Обычные математические пакеты, типа вольфрам математики - они под оптимизирующие трансформации не затачивались, так что для решения таких задач нужно будет что-то специализированное городить.

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

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

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

                                                                                    У тебя есть примеры таких либ в языках с гомоиконностью/доступом к AST?
                                                                                    Ответить
                                                                                    • > У тебя есть примеры таких либ в языках с гомоиконностью/доступом к AST?

                                                                                      Source-to-source трансляторы есть, например вот https://spiral.imperial.ac.uk/bitstream/10044/1/42498/1/Gao-X-2016-PhD-Thesis.pdf

                                                                                      > This thesis introduces a new technique, and its associated tool SOAP, to automatically perform source-to-source optimization of numerical programs, specifically targeting the trade-off among numerical accuracy, latency, and resource usage as a high-level synthesis flow for FPGA implementations.

                                                                                      Очевидно, что для source-to-source трансляции нужно как-то получить AST и что-то там трансформировать
                                                                                      Ответить
                                                                                      • A new method is proposed and carried out in SOAP that performs general numerical
                                                                                        program transformation for the trade-off optimization among accuracy, and two resource
                                                                                        related metrics, LUT and DSP utilizations. To optimize a numerical program, it starts by
                                                                                        abstracting the program into a MIR, which we designed to extract the essence of executing
                                                                                        the program, and removes unnecessary informations such as temporary variables,
                                                                                        interleaving of non-dependent statement, etc. The MIR is then optimized efficiently by
                                                                                        discovering a wide range of equivalent trade-off implementations of the original MIR.
                                                                                        An optimized MIR can then be chosen to be translated into a numerical program.

                                                                                        В этой работе авторы используют подход "шланга": компилирует код (очень ограниченное подмножество сишки) в "metasemantic intermediate representation", оптимизируют его, после чего "раскукоживают" обратня в код. Причём, что интересно, весь код для оптимизации у них няписан ня Python, потому что ня Python писать подобные высокоуровневые преобразования очень удобня.

                                                                                        Никакой трансформации AST в этой работе нят.
                                                                                        Ответить
                                                                                    • Или вот например https://tel.archives-ouvertes.fr/tel-02443231/document

                                                                                      > 2.1.2 Existing Tools for Source-to-Source Transformation
                                                                                      Ответить
                                                                                      • > Our goal is to develop a framework will allow to perform of source code transformations based on performance analysis tools metrics.
                                                                                        Гомоиконность/доступ к AST для этой работы вообще никак ня релевантны.

                                                                                        > Existing Tools
                                                                                        А где здесь библиотеки? Это просто либо компиляторы, либо standalone утилиты, работающие с IR. Как им поможет доступ к AST изнутри языка?
                                                                                        Ответить
                                                                                        • Это какие-то утилиты для инструментации промежуточного кода типа джавьего ломбока и AspectJ и типа того, как ябло в llvmный код добавляло ARC?
                                                                                          Ответить
                                                                                          • > Это какие-то утилиты для инструментации промежуточного кода типа джавьего ломбока и AspectJ и типа того, как ябло в llvmный код добавляло ARC?

                                                                                            Это можно и для инструментации, и для оптимизации. Например, ROSE что-то там умеет в плане автораспараллеливания, ему можно скормить код на крестах и он может в ответ высрать код на крестах с всякими там "#pragma omp parallel for" для циклов

                                                                                            1.3 Problems that ROSE can address ROSE is a mechanism to build source-to-source analysis or optimization tools that operate directly on the source code of large scale applications. Example tools that have been built include:

                                                                                            •OpenMP translator,
                                                                                            •Array class abstraction optimizer,
                                                                                            •Source-to-source instrumenter,
                                                                                            •Loop analyzer,
                                                                                            •Symbolic complexity analyzer,
                                                                                            Ответить
                                                                                        • > Гомоиконность/доступ к AST для этой работы вообще никак ня релевантны.

                                                                                          Вполне релевантны. Из кода получают AST, с AST делают некие преобразования и обратно выплевывают код. http://rosecompiler.org/uploads/ROSE-Tutorial.pdf#part.4 - вот тут что-то такое описывается.

                                                                                          > А где здесь библиотеки?

                                                                                          Тебе нужен пример, библиотеки, которую можно таким методом заоптимизировать? Или тебе нужен пример библиотеки, где официально сами разработчики применяют некие source-to-source оптимизирующие трансформации? Ну например вот https://engineering.purdue.edu/Cetus/cetusworkshop/papers/4-1.pdf

                                                                                          > ROSE is being used by several DOE projects to address the challenges of exascale computing. One of the projects, Thrify, is using ROSE to explore novel compiler analysis and optimization to take advantage of an exascale architecture with many-core chips specially designed to improve performance per watt. In another project, CODEX, an alternative simulator is used to support the analysis of kernels from DOE applications using other proposed exascale node architectures and possible future network connection topologies and hardware. In still another project, ROSE has been used to analyze example applications and extract the MPI us-age as an input code to support evaluation of message passing to support the network communication simulation

                                                                                          > Как им поможет доступ к AST изнутри языка?

                                                                                          Тогда это делалось бы через этот доступ к AST внутри самого языка, не требовалось бы получать AST из исходного кода специальной хренью и потом обратно генерировать синтаксически валидный код, работать надо было б на уровне AST. Это несколько удобнее.
                                                                                          Ответить
                                                                                          • Нят, в принципе ня релевантны.

                                                                                            Проблема в том, что всё тобою скинутое — это отдельные утилиты. Они берут исходный код, проводят няд ним изменения и выдают изменённый исходник обратно. Каким образом им может помочь доступ к AST во время компиляции?

                                                                                            > работать надо было б на уровне AST
                                                                                            Во-первых, каким образом скинутая тобой либа будет получать данные PGO во время компиляции?
                                                                                            Во-вторых, оптимизации подобного уровня (векторизация, снижение точности и так далее) няльзя делать "под капотом". Программист должен видеть, что получилось ня выходе, иняче его ждут незабываемые часы отладки. Совсем нядавно bormand рассказывала, как у него компилятор превратил цикл в самописном memcpy в вызов memcpy. Так что ещё более радикальная оптимизация кода должна проводиться исключительня в виде source-to-source, а не в виде "говнолиба перемешала AST так, что отлаживать это можня только под грибами".
                                                                                            Ответить
                                                                                            • > Нят, в принципе ня релевантны.

                                                                                              Обоснование?

                                                                                              > Проблема в том, что всё тобою скинутое — это отдельные утилиты. Они берут исходный код, проводят няд ним изменения и выдают изменённый исходник обратно. Каким образом им может помочь доступ к AST во время компиляции?

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

                                                                                              > Во-первых, каким образом скинутая тобой либа будет получать данные PGO во время компиляции?

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

                                                                                              > Во-вторых, оптимизации подобного уровня (векторизация, снижение точности и так далее) няльзя делать "под капотом". Программист должен видеть, что получилось ня выходе, иняче его ждут незабываемые часы отладки.

                                                                                              Если либой гарантируется сохранение наблюдаемого поведения и в либе нет никаких багов, то никаких часов отладки не требуется.

                                                                                              Кстати, а как с этим обстоят дела у крестошаблонного метапрограммирования? Программист обязательно должен видеть, во что трансформируется такая-то шаблонометушня?

                                                                                              > Так что ещё более радикальная оптимизация кода должна проводиться исключительня в виде source-to-source, а не в виде "говнолиба перемешала AST так, что отлаживать это можня только под грибами".

                                                                                              Если перемешивание AST точно не меняло наблюдаемого поведения, можешь отлаживать неперемешанный вариант. Если у тебя перемешанный вариант неправильно что-то считает, неперемешанный будет вести себя ровно так же.
                                                                                              Ответить
                                                                                              • > Обоснование?
                                                                                                Они работают с IR. AST им ня нужен.

                                                                                                > Эти утилиты можно было бы написать на метаязыке, который бы выполнялся во время компиляции. Это мог бы быть например некий хитрый плагин к компилятору, который бы встраивался в процесс компиляции и делал нужные перестановки AST.
                                                                                                А зачем, если ня Питоне эти утилиты писать быстрее и проще?

                                                                                                > Можно инклудить в компилтайм-либу накопленные данные профилирования в каком-то формате, этот файл может быть проанализирован на этапе компиляции, и потом там что-то можно трансформировать в самом коде.
                                                                                                И это замечательный пример того, как программисты, узнавшие про какой-то новый концепт, нячинают пытаться засунуть его в любое место, даже если в итоге получается переусложнённое говно.

                                                                                                > гарантируется сохранение наблюдаемого поведения и в либе нет никаких багов
                                                                                                Святая няивность!

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

                                                                                                > можешь отлаживать неперемешанный вариант.
                                                                                                Программа крашнулась у пользователя. Дамп есть, сейчас отладим!.. Ой, нят, извините, этот дамп с оптимизированной версии, в которой AST перемешано до няузнавания, отладить это ня получится.

                                                                                                > Если у тебя перемешанный вариант неправильно что-то считает, неперемешанный будет вести себя ровно так же.
                                                                                                Очень смешно. Кстати, замена цикла ня memcpy тоже ня меняет наблюдаемого поведения.

                                                                                                > Кстати, а как с этим обстоят дела у крестошаблонного метапрограммирования?
                                                                                                Ня сильня хуже, чем у программы без шаблонов. В дебаг-символах все специализации шаблонов сохраняют имена, просто к ним добавляются аргументы шаблона. В крайнем случае можня сходить ня https://cppinsights.io и посмотреть, во что конкретня раскрывается конкретное шаблоноговно. С AST так ня сделаешь.
                                                                                                Ответить
                                                                                                • > Они работают с IR. AST им ня нужен.

                                                                                                  А этот IR откуда берется? Случайно не из AST? А если AST и IR на каком-то этапе это одно и то же?

                                                                                                  > А зачем, если ня Питоне эти утилиты писать быстрее и проще?

                                                                                                  Почему Clang-LLVM и GCC еще не переписали на питон?

                                                                                                  > Святая няивность!

                                                                                                  Так понятно что баги есть даже в компиляторах, и что?

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

                                                                                                  Так ведь даже компиляторы C/C++ с точностью для FPU-вычислений хер знает что делают, и там ничего не гарантируется.

                                                                                                  > Программа крашнулась у пользователя. Дамп есть, сейчас отладим!.. Ой, нят, извините, этот дамп с оптимизированной версии, в которой AST перемешано до няузнавания, отладить это ня получится.

                                                                                                  Оптимизирующие компиляторы тоже отлично справляются с задачей перемешивания "AST" до неузнаваемости, и без дебаг-инфы там тоже все сложно будет.

                                                                                                  >> Если у тебя перемешанный вариант неправильно что-то считает, неперемешанный будет вести себя ровно так же.
                                                                                                  >Очень смешно.

                                                                                                  Именно так и работают флаги оптимизации у всяких разных компиляторов, если нет UB и багов в компиляторе. Они делают программу быстрее, но поведение не меняется. Это смешно?
                                                                                                  Ответить
                                                                                                  • > А этот IR откуда берется? Случайно не из AST?
                                                                                                    Почитай работу, откуда он там берётся. Но это, разумеется, совершення няважно, потому что в итоге авторы манипулируют не AST, а IR. Возможня, потому что умным дяденькам и тётенькам манипуляция AST няпрямую показалась слишком сложной.

                                                                                                    > Почему Clang-LLVM и GCC еще не переписали на питон?
                                                                                                    А почему утилита по твоей ссылке няписана на Питоне?

                                                                                                    > Так понятно что баги есть даже в компиляторах, и что?
                                                                                                    То, что ты тут размахиваешь либой, которая гарантирует няприкосновенность кода. В реальнясти такую гарантию может дать только либа, которая побайтово копирует код из одного файла в другой.

                                                                                                    > Так ведь даже компиляторы C/C++
                                                                                                    Проблема в том, что скинутая тобой либа нямерянно меняет поведение программы. Если бы оня это делала неявня, через AST — программисту было бы очень весело.

                                                                                                    > и без дебаг-инфы там тоже все сложно будет.
                                                                                                    Да. Проблема в том, что после работы твоей волшебной либы, перемешивающей AST, ня поможет даже дебаг-инфа.

                                                                                                    > Именно так и работают флаги оптимизации у всяких разных компиляторов, если нет UB и багов в компиляторе. Они делают программу быстрее, но поведение не меняется.
                                                                                                    Только вот проблема в том, что существенная часть ошибок в коде ня C/C++ — это имення UB. И даже сейчас UB может приводить к очень странным и трудно отлавливаемым багам. А твоя волшебная либа только ухудшает ситуацию.
                                                                                                    Ответить
                                                                                                    • > Но это, разумеется, совершення няважно, потому что в итоге авторы манипулируют не AST, а IR.

                                                                                                      А что если на каком-то этапе AST == IR и трансформации в таком абстрактном представлении где-то происходят? Или так не может быть?

                                                                                                      > А почему утилита по твоей ссылке няписана на Питоне?

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

                                                                                                      > В реальнясти такую гарантию может дать только либа, которая побайтово копирует код из одного файла в другой.

                                                                                                      Нет. Для начала надо формально доказать, что компилятор, который собирал эту либу, всё правильно скомпилировал, а еще что космическое излучение не повлияло на процесс, и что в процессоре нет аппаратных багов и еще куча всего можно понапридумывать.

                                                                                                      > Проблема в том, что скинутая тобой либа нямерянно меняет поведение программы.

                                                                                                      И что? Некоторые оптимизации тоже вполне намеренно меняют поведение программы. Например, -funsafe-math-optimizations

                                                                                                      > Да. Проблема в том, что после работы твоей волшебной либы, перемешивающей AST, ня поможет даже дебаг-инфа.

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

                                                                                                Тогда это очень сильно ограничивает манипуляции над AST. По сути, ничего кроме оптимизаций запилить невозможно.

                                                                                                Вот сгенерил ты во время конпеляции какую-нибудь сериализацию/десериализацию для структуры и тем самым поменял наблюдаемое поведение (добавил новое).

                                                                                                А ты ведь манипуляции над AST хочешь юзать для новых фич языка и т.п.
                                                                                                Ответить
                                                                                                • > А ты ведь манипуляции над AST хочешь юзать для новых фич языка и т.п.

                                                                                                  Если нужно новые фичи языка добавлять, не имеет смысла говорить о "неизменении наблюдаемого поведения" т.к. расширенный язык (условно говоря C++) не скомпилируется компилятором нерасширенного языка (условно говоря компилятором C). И никакого наблюдаемого поведения у некомпилирующейся программы нет, так что постановка вопроса некорректна.
                                                                                                  Ответить
                                                                                                  • Да, но это ведь не означает, что можно нагенерить хуйни и юзер будет доволен.

                                                                                                    Это скорее означает, что "простой" вариант с сохранением поведения тут не катит. И придётся как-то формализовывать эту фичу, описывать её взаимодействие с другими. Ну, то чем сейчас и занимаются комитеты. Только из-за зоопарка этих библиотек-расширений багов в реализации и недочётов в спеке будет на порядок больше.

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

                                                                                              А часто ли программист должен смотреть ассемблерный выхлоп из компилятора? Ну там ведь тоже куча всяких сложных трансформаций происходит, что-то куда-то заинлайнивается, loop-invariant code motion всякие происходят, loop unswitching, т.е. вместо кода типа
                                                                                              int i, w, x[1000], y[1000];
                                                                                              for (i = 0; i < 1000; i++) {
                                                                                                x[i] += y[i];
                                                                                                if (w)
                                                                                                  y[i] = 0;
                                                                                              }

                                                                                              компилятор где-то в каком-то абстрактном говнопредставлении перетрансформирует это в
                                                                                              int i, w, x[1000], y[1000];
                                                                                              if (w) {
                                                                                                for (i = 0; i < 1000; i++) {
                                                                                                  x[i] += y[i];
                                                                                                  y[i] = 0;
                                                                                                }
                                                                                              } else {
                                                                                                for (i = 0; i < 1000; i++) {
                                                                                                  x[i] += y[i];
                                                                                                }
                                                                                              }

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

                                                                                                  Ну ещё иногда конпелятор генерит говно и приходится читать что он там высрал. Но это прям крайне редко.
                                                                                                  Ответить
                                                                                                  • > конпелятор генерит говно
                                                                                                    ну это почти или даже за рамками задач обычного генерал-пурпоза прогармиста
                                                                                                    вопрос доверия к инструменту как бы
                                                                                                    Ответить
                                                                                          • Я баловался с TH и написал в прод несколько питушень с трансформацией AST на Erlang, и могу сказать, что метушня — это совсем не весело.
                                                                                            Вместо проблем у тебя появляются метапроблемы.
                                                                                            И если не делать трансформации AST с помощью сахарка в языке (квазицитирования и сплайсов, как в TH), то через месяц читать свой мета-код становится очень интересно.
                                                                                            Ответить
                                                                                            • > Я баловался с TH и написал в прод несколько питушень с трансформацией AST на Erlang, и могу сказать, что метушня — это совсем не весело.

                                                                                              Вряд ли крестовые шаблоны в этом плане веселее.
                                                                                              Ответить
                                                                                              • Если не доводить их до абсурда^W modern C++, то чуть веселее, всё-таки.
                                                                                                Сравни типичное шаблоноговно (не из буста) с
                                                                                                https://github.com/k32/typerefl/blob/master/src/typerefl_trans.erl (и это ещё очень простая трансвормация)
                                                                                                Ответить
                                                                                                • Но, к чести трансформаций AST, они могут куда больше, чем шаблоны, конечно.
                                                                                                  Ответить
                                                                                                • P.S.
                                                                                                  mk_literal_list(Line, List) ->
                                                                                                    mk_literal_list(Line, fun(A) -> A end, List).
                                                                                                  
                                                                                                  make_additional_attrs_ast(Name, Line, State) ->


                                                                                                  Какая консистентность именования )))
                                                                                                  Ответить
                                                                                              • Крестовые шаблоны не порождают новый код и не удаляют старый. Они просто раскрываются.

                                                                                                К слову, даже на родине гомоикон в лиспе все почему-то стараются юзать квазицитирование а не гомоиконы... Хотя казалось бы.
                                                                                                Ответить
                                                                                                • В списке требований MELPA (репа для elisp-пакетов) есть требование не юзать, сука, макросы без нужды.
                                                                                                  Так что даже лисперам лень в чужих говноиконах копаться.
                                                                                                  Ответить
                                                                                                • > Крестовые шаблоны не порождают новый код и не удаляют старый. Они просто раскрываются.

                                                                                                  И при раскрытии могут порождать некий новый код? Вот например компилтайм-либа крестов для PCRE https://github.com/hanickadot/compile-time-regular-expressions - она что, ничего не порождает? Что вообще значит "порождает новый код"? BOOST_PP_REPEAT порождает или не порождает новый код? А что тогда порождает?
                                                                                                  Ответить
                                                                                                  • > PCRE

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

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

                                                                                                      Демагогия какая-то. Следуя такой логике, тогда и обычный компилятор ничего не порождает, когда компилирует что-то из кода на Си в инструкции процессора. Ведь код компилятора написан заранее, компилируемый компилятором код написан заранее, из компилируемого кода собирается какое-то дерево и потом по каким-то известным правилам во что-то трансформируется.

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

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

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

                                                                                                          И что? Ну вот есть допустим некий крестовый шаблон, возьмем простейший вариант, без всякой сложной метушни
                                                                                                          template <typename T>
                                                                                                          T add_crap (T a, T b)
                                                                                                          {
                                                                                                            return a + b;
                                                                                                          }


                                                                                                          И где-то я использую эту хрень таким образом
                                                                                                          auto func_ptr = add_crap<int>;


                                                                                                          Отчего бы мне не считать, что делая подобную хрень, я автоматически генерирую (порождаю) где-то функцию типа
                                                                                                          int add_crap_int(int a, int b)
                                                                                                          {
                                                                                                            return a + b;
                                                                                                          }

                                                                                                          ?
                                                                                                          Ответить
                                                                                                          • Ну можно и так считать... Тут важно, что double add_crap_foobar(int a, float z) { return pow(a, z); } он никогда не сгенерит из того шаблона. С этим ты согласен?
                                                                                                            Ответить
                                                                                          • Сколь я понял, тебя просят показать пример либы в языке с доступом к аст где это дало какую-то полезную оптимизацию типа той что ты описываешь.
                                                                                            Ответить
                                                                                            • > тебя просят показать пример либы в языке с доступом к аст где это дало какую-то полезную оптимизацию типа той что ты описываешь.

                                                                                              Сейчас, увы, нет широко используемых и достаточно низкоуровневых языков с доступом к AST в компилтайме, чтобы там такая оптимизация была реально полезной.
                                                                                              Ответить
                                                                                              • На питоне есть inliner, функции / методы инлайнит, производительность возрастает.
                                                                                                Ответить
                                                                        • > Ты AST структур будешь ручками парсить, вместо простого "getFields<struct X>"?

                                                                          Будут либы, которые напрямую работают с AST, и делая условный "getFields<struct X>" я как раз буду такую либу использовать. Но чтоб такие либы написать, нужен доступ к AST.
                                                                          Ответить
                                                                          • Подход "дайте программистам удочку, а они сами няделают либы ня все случаи жизни" в реальнясти, увы, ня работает. Посмотри, во что превратился nodejs + npm.
                                                                            Ответить
                                                                            • > Подход "дайте программистам удочку, а они сами няделают либы ня все случаи жизни" в реальнясти, увы, ня работает. Посмотри, во что превратился nodejs + npm.

                                                                              А что получилось в C/C++? Полуработающий Conan, в котором хрен чего найдешь, и поэтому один фиг надо ходить по гитхабу с черным мешком для мусора и собирать в него нужные говнолибы? Это лучше?
                                                                              Ответить
                                                                    • > Большинство задач, возникающих при няписании обобщённого кода, шаблоны решают хорошо и эффективня.

                                                                      Я вот кстати посмотрел такую либу https://github.com/hanickadot/compile-time-regular-expressions - это вот регулярки через шаблоны в компилтайме, с запиленным в компилтайме LL(1) анализатором на шаблонах. И там еще вот такая генеренная шаблонная хрень из какого-то DESATOMAT
                                                                      // https://github.com/hanickadot/compile-time-regular-expressions/blob/main/include/ctre/pcre.hpp
                                                                      
                                                                      	using _others = ctll::neg_set<'!','"','$','\x28','\x29','*','+',',','-','.','/',':','<','=','>','?','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_','a','b','c','d','e','f','g','h','0','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\x7B','|','\x7D','1','2','3','4','5','6','7','8','9'>;
                                                                      	static constexpr auto rule(s, ctll::term<'\\'>) -> ctll::push<ctll::anything, backslash, repeat, string2, content2>;
                                                                      	static constexpr auto rule(s, ctll::term<'['>) -> ctll::push<ctll::anything, c, repeat, string2, content2>;
                                                                      ...


                                                                      Да, нагенерить километры какой-то шаблонной хрени это прямо вот "хорошо и эффективно". На кой вообще делать кодогенерированную компилтайм-либу на шаблонах которая генерит регекспы в компилтайме, если сами регекспы можно сразу кодогенерировать?
                                                                      Ответить
                                                            • Вот например есть задача https://govnokod.ru/27403#comment626280 которая средствами внутри крестов вообще никак не решается, даже в самом-самом последнем говностандарте, и решается только какими-то внешними костылями-препроцессорами. Означает ли это, что кресты - говно? А что должно означать?
                                                              Ответить
                                                              • > Означает ли это, что кресты - говно?
                                                                Нязвать язык программирования говном можня только после обширного анялиза его нядостатков. То, что кресты ня могут решить эту задачу, ознячает лишь то, что они ня могут решить эту задачу (хотя в принципе, конячно, кресты — говно, с этим никто ня спорит).

                                                                Простыми словами: я купила машину, а в машине нят прикуривателя. Ознячает ли это, что машина — говно?
                                                                Ответить
                                                                • >обширного анялиза его нядостатков

                                                                  я сколько тут сижу вы столько тут анализируете недостатки с++
                                                                  Ответить
                                                              • нахрюк конечно в стиле "си -- говно, потому что в стандартной библиотеке там нет JSON"
                                                                Ответить
                                                            • Может если я куплю молоток, забью им пару гвоздей и он после этого нахрен сломается, то молоток не говно, это просто он так хреново устроен, малый ресурс забивания гвоздей?
                                                              Ответить
                                                              • https://ru.wikipedia.org/wiki/Парадокс_кучи
                                                                Парадокс говна («Говно», «Моча») — логический парадокс, сформулированный Евбулидом из Говнокода (IV век до н. э.)[1], связанный с неопределённостью предиката «быть говном»[2].


                                                                Слишком малый ресурс при слишком высокой цене — конячно, говно. А что такое малый ресурс и что такое высокая цена — тут уже каждый решает для себя.
                                                                Ответить
                                                              • если на али за $1.99 free shipping, то да
                                                                Ответить
                                            • > Ня крестах же программируют, а ня упражняются в эзотерике (ну, по большей части).

                                              Разрабы Boost программируют или упражняются в эзотерике?
                                              Ответить
                                          • Ебанутая претензия конечно. А если бы такие абсракции были, ты их представляешь себе zero-cost?
                                            Ответить
                                            • >А если бы такие абсракции были, ты их представляешь себе zero-cost?

                                              Компилтайм-метушня вполне может (и должна) быть zero-cost.
                                              Ответить
                                              • Тут главное ня дометушиться до того, что компилятору нячнёт требоваться JIT, чтобы нябольшой проектик собирать меньше часа.
                                                Ответить
                                                • Мало вам тюрингполности процесса компиляции
                                                  Ответить
                                              • Пожалуй да.
                                                Ответить
                              • Может на препроцессоре можно такое сделать? Завести а = SUPER_CONCAT(b, с) который в случае совпадения a и b раскрывается в append а иначе в cat?
                                Ответить
                                • Ну это если ты условие в макросне пропишешь сравнение указателей, только оно будет в рантайме проверяться.

                                  https://wandbox.org/permlink/BjVlfoT12mb8xQFp
                                  Ответить
                                  • Хотя можно еще стрингифицировать в CHOOSE имя первой и второй переменной, и компилтаймово их сравнивать constexpr-функцией.
                                    https://wandbox.org/permlink/eBiqs8lco7J3IMww

                                    constexpr bool strings_equal(char const * a, char const * b) {
                                        return *a == *b && (*a == '\0' || strings_equal(a + 1, b + 1));
                                    }
                                    
                                    #define CHOOSE(a,b,c) \
                                    if constexpr (strings_equal(#a, #b)) \
                                    { \
                                      vec_uint8_append(a,c); \
                                    } \
                                    else \
                                    { \
                                      (a) = vec_uint8_cat(b,c); \
                                    }

                                    Блядь, какое же говно. И все равно это будет недостаточно универсально.
                                    Ответить
                                    • И всё ради того, чтобы ня писать +=.
                                      Ответить
                                      • > И всё ради того, чтобы ня писать +=.

                                        А зачем мне надо выбирать, писать "x += y" или "x = y + z"? Ведь вполне может быть так, что из каких-то там шаблонов или макросов или смеси шаблонов и макросов раскрывается такая вот фигня вида "x = x + y" и мне надо чтоб оно там само это нашло и переписало в "x += y" для максимального пирфоманса.
                                        Ответить
                                        • > А зачем мне надо выбирать, писать "x += y" или "x = y + z"?
                                          Чтобы ясно выразить, что в первом случае ты хочешь сразу модифицировать x, а во втором — снячала сложить, а потом записать в x.

                                          > Ведь вполне может быть
                                          Ни разу ня видела таких шаблонов. Приведи пример из реального проекта, в котором такая оптимизация могла бы улучшить производительность.
                                          Ответить
                                          • > Чтобы ясно выразить, что в первом случае ты хочешь сразу модифицировать x, а во втором — снячала сложить, а потом записать в x.

                                            А если я хочу получить нужный мне конечный результат максимально эффективным образом, а что оно там сначала и что потом делает - меня не волнует?

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

                                            Лично я таких проектов не знаю. Искать лень.
                                            Ответить
                                            • > А если я хочу получить нужный мне конечный результат максимально эффективным образом, а что оно там сначала и что потом делает - меня не волнует?
                                              Тогда ты используешь только +=.

                                              > Лично я таких проектов не знаю. Искать лень.
                                              И я ня зняю. И с учётом крайней оторванности этой задачи от реальности — скорее всего, если такие проекты и есть, то встречается няобходимость в этом "автосворачивании операторов" раз на миллиард sloc.
                                              Ответить
                                              • > Тогда ты используешь только +=.

                                                А если у меня откуда-то синтезируется код с a = a + b и я хочу этот код преобразовать в a += b ?
                                                Ответить
                                                • > откуда-то синтезируется код

                                                  Дык нет в крестах "синтеза кода откуда-то". Весь код уже написан тобой. Просто параметризуется немножко. Поэтому либо ты сам уже написал a += b либо там всегда и будет c = a + b, которое никуда не преобразовать.
                                                  Ответить
                                                  • > Дык нет в крестах "синтеза кода". Весь код уже написан тобой.

                                                    Ну написан, и что? Вот есть макрос, допустим
                                                    #define SHIT(a, b, c) a = b + c

                                                    Если я его вызову как
                                                    int a = 5;
                                                    int b = 6;
                                                    SHIT(a,a,b); // он раскроется тут в a = a + b, но никак не в a += b.
                                                    // хотя дальше оптимизатор уже порешает.
                                                    Ответить
                                                    • > Вот есть макрос, допустим

                                                      Обколются своих макросов, а потом в жопы ебутся...
                                                      Ответить
                                  • Всмысле в рантайме? То есть препроцессор с условием высрет реального кода в аутпут? Не только она уровне кода замены сделает?

                                    Охуеть.
                                    Ответить
                                    • > препроцессор с условием

                                      Препроцессор с условием просто высрет это условие в код. Он же просто токенами ворочает. А условие, если оно не constexpr, будет выполнено уже в рантайме.

                                      З.Ы. А #ifdef внутри макроса нельзя юзать, если ты о нём.
                                      Ответить
                                      • >если оно не constexpr
                                        и если компилятор не докажет, что оно константа:)

                                        Кстати, в няшной же нет constexpr?
                                        Ответить
                                        • > Кстати, в няшной же нет constexpr?

                                          Ключевого слова нет. А само понятие, типа "известная на этапе компиляции фигня" - есть.

                                          так скомпилируется:
                                          int a[6*6] = {6};


                                          Так тоже скомпилируется в GCC и Clang, но это уже экстеншен:
                                          int a[(int)(0.002*1000)];

                                          warning: variably modified 'a' at file scope


                                          А вот так нихуя не скомпилируется:
                                          int b[rand()];


                                          И так тоже не скомпилируется:
                                          const int crap = 666;
                                          int a[crap];
                                          Ответить
                                          • > известная на этапе компиляции фигня

                                            Значения енумов и метки в свиче ещё требуют "constexpr". В общем-то как и в крестах.
                                            Ответить
                                          • > А само понятие, типа "известная на этапе компиляции фигня" - есть.

                                            Это к щастю везде есть) Кажется, что "int i = 2 + 2" даже javac поймет

                                            >И так тоже не скомпилируется:
                                            хм.. а это не VLA?

                                            VC не умеет VLA, но GCC то вроде должен уметь?
                                            Ответить
                                            • > хм.. а это не VLA?

                                              Хмм, ну да, с VLA оно скомпилируется, но оно не будет компилироваться, если эта хрень объявлена глобально. Глобальный массив не может быть VLA.
                                              Ответить
                                              • >Глобальный массив не может быть VLA.
                                                пушо стек еще как-то можно двигать в рантайме, а вот размер data и bss нужно знать заранее?
                                                Ответить
                                                • Да. VLA — это просто сахарок няд alloca().
                                                  Ответить
                                                  • Тока аллока был необязателен, а vla уже стал частью стандарта.
                                                    В C99 появился.

                                                    А вот в C89 (который был и в bolrand c++ 3) мало того, что не было VLA, так еще и все локальные переменные нужно было декларировать в начале тела функции.

                                                    То есть размер стекфрейма функции компилятор всегда мог посчитать перед началом функции.

                                                    Кcтати, а в С++ вместо VLA принято использовать vector, который всё хранит в куче? Или он может как-то читерить, и хранить на стеке через alloca?
                                                    Ответить
                                                    • А в паскале вообще все декларации это синтаксически отдельная от тела функции часть кода, и это заебись.
                                                      Ответить
                                                      • >заебись
                                                        согласен

                                                        Возможность объявлять переменные походу энкариджит говнокодеров высирать функции на 900 строк
                                                        Ответить
                                                    • Про с89, я думал что это примерно как в паскале, для дисциплины программиста. Компилятору-то что мешает посчитать? типа код вида

                                                      if (cond) int a = 1; else double b = 1.0;

                                                      ?

                                                      А он кстати во что скомпилится в с99?
                                                      Ответить
                                                      • > во что скомпилится в с99

                                                        Внихуя. Переменные же не используются (а использовать ты их не сможешь).

                                                        З.Ы. А, вообще не компилится, лол. Скобочки просит.
                                                        Ответить
                                                        • Ну я имел ввиду что-то типа
                                                          void foo() {
                                                          	int i = rand();
                                                          
                                                          	if (i % 2 > 0) {
                                                          		int a = 1;
                                                          		a += 2;
                                                          		printf("neg %d\n", a);
                                                          	} else {
                                                          		double b = 1.0;
                                                          		b += 2.0;
                                                          		printf("pos %f\n", b);
                                                          	}
                                                          }
                                                          Ответить
                                                          • судя по годболту, он сначала выделил место
                                                            >sub rsp, 32

                                                            если добавить еще int, то будет 48

                                                            а потом пишет твою "a" в одно и тоже место

                                                            mov DWORD PTR [rbp-8], 1
                                                            add DWORD PTR [rbp-8], 2

                                                            ну тоись он пошел, посчитал размер стека, двиганул SP (предвроительно сохранив его в BP) и дальше жег

                                                            А что бы он делал с FPO кстати я не зна, надо проверит
                                                            Ответить
                                                            • foo():
                                                                      push    rbp
                                                                      mov     rbp, rsp
                                                                      sub     rsp, 32
                                                                      call    rand
                                                                      mov     DWORD PTR [rbp-4], eax
                                                                      mov     eax, DWORD PTR [rbp-4]
                                                                      cdq
                                                                      shr     edx, 31
                                                                      add     eax, edx
                                                                      and     eax, 1
                                                                      sub     eax, edx
                                                                      test    eax, eax
                                                                      jle     .L2
                                                                      mov     DWORD PTR [rbp-20], 1
                                                                      add     DWORD PTR [rbp-20], 2
                                                                      mov     eax, DWORD PTR [rbp-20]
                                                                      mov     esi, eax
                                                                      mov     edi, OFFSET FLAT:.LC0
                                                                      mov     eax, 0
                                                                      call    printf
                                                                      jmp     .L4
                                                              .L2:
                                                                      movsd   xmm0, QWORD PTR .LC1[rip]
                                                                      movsd   QWORD PTR [rbp-16], xmm0
                                                                      movsd   xmm1, QWORD PTR [rbp-16]
                                                                      movsd   xmm0, QWORD PTR .LC2[rip]
                                                                      addsd   xmm0, xmm1
                                                                      movsd   QWORD PTR [rbp-16], xmm0
                                                                      mov     rax, QWORD PTR [rbp-16]
                                                                      movq    xmm0, rax
                                                                      mov     edi, OFFSET FLAT:.LC3
                                                                      mov     eax, 1
                                                                      call    printf
                                                              .L4:
                                                                      nop
                                                                      leave
                                                                      ret


                                                              То есть всё равно посчитал всё место, какое ему может понадобиться в любом из ветвлений, и отожрал стека, а потом, возможно, часть отожранного стека не юзал?

                                                              Это практически то же самое, что просто собрать все декларации, так как если бы они были написаны в начале функции, только синтаксически разрешить писать их не в начале, или я не прав?
                                                              Ответить
                                                              • ну да)

                                                                попробуй
                                                                #include <random>
                                                                void foo() {
                                                                	int i = rand();
                                                                
                                                                	if (i % 100500) {
                                                                        long int a = 1, b = 1, c = 1, d = 1;        
                                                                        int q = 0;
                                                                		a += 2;
                                                                		printf("neg %d %d %d %d", a,b,c,d);
                                                                	} else {
                                                                		double b = 1.0;
                                                                		b += 2.0;
                                                                		printf("pos %f", b);
                                                                	}
                                                                }

                                                                получишь
                                                                sub     rsp, 80


                                                                Единственный плюс "нового" подхода это ограничение видимости. Оно позволяет иметь "b" внутри каждой веточки своё.

                                                                Ну и вероятно деструкторы должны вызываться в случае С++.

                                                                Забавнее посомтреть что будет, если крутить стек в рантайме

                                                                VLA
                                                                int i = rand();
                                                                int j[(int)i];

                                                                начинаются игрища с стек поинтером
                                                                imul    rax, rax, 16
                                                                        sub     rsp, rax
                                                                        mov     rax, rsp


                                                                Удивительно другое!

                                                                Я заказал "-fomit-frame-pointer" чтобы посмотреть как питух будет изъебываться адресовать переменные от SP, которого он постоянно дрочит.

                                                                А он взял, и положил на эту опцию, и продолжил юзать BP.

                                                                При этом если сделать код без VLA, то -fomit-frame-pointer отключает BP, и переменные начинают адресоваться от SP.

                                                                Иными словами, FPO значит не "запрещаю тебе юзать BP" (как я до сего момента думал), а означает "разрешаю тебе не юзать BP, если хочешь"

                                                                А компилятор такой: ой, ну если бы ты не трогал SP в рантайме, то я бы воспользовался твоим предложением, а так засунь себе FPO в жопу, а я буду продолжать адресовать переменные на стеке от BP
                                                                Ответить
                                                                • > значит не "запрещаю тебе юзать BP"
                                                                  Ну да, абсолютное большинство "оптимизирующих" опций — это рекомендации, а ня законы (прямо как Кодекс в PoTC \(★ω★)/).
                                                                  Ответить
                                                                  • ну если вдуматься, то да: BP с точки зрения программиста нужен только чтобы раскручивать стек без символов.

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

                                                                    Хотя наверное в x64 регистров уже так много, что смысл экономить на BP нет
                                                                    Ответить
                                                                • > sub rsp, 80

                                                                  Напоминает "record case" или variable records в паскале.

                                                                  Там можно объявить запись с вариантами разблядовки типов, например
                                                                  Type
                                                                      Sex = (baba, mojeek);
                                                                  
                                                                      Hair = (lysy, volosaty);
                                                                  
                                                                      Chelovek = Record
                                                                          age: Integer;
                                                                          hair: Hair,
                                                                          case Sex of
                                                                              baba: (razmer_sisek: Integer, ebalo: Kartinka);
                                                                              mojeek: (zarplata: Double,  dlinna_huya: Byte);
                                                                          end;
                                                                  end;


                                                                  В итоге сайзоф такой записи будет исходя из размера самого ресурсоёмкого case, но не всей их суммой. Все case замапятся в одно и то же место в памяти и гарантированно влезут. В данном примере попытавшись изменить razmer_sisek у записи можно поломать его значение zarplata, потому что предполагается что юзаться кейсы должны независимо. Компилятор за этим не следит, ты сам в коде должен определить для себя, какой тебе от этой записи нужен кейс. Таким образом можно знатно сэкономить на спичках.
                                                                  Ответить
                                                                  • В сишке это называется "union"

                                                                    union my_union
                                                                    {
                                                                    	char c;
                                                                    	int i;
                                                                    };


                                                                    sizeof этой конструкции будет равен int (мы предпологаем, что int выравнивать не нужно).

                                                                    Если ты положил туда i, то в "с" теперь UB, и наоборот.
                                                                    Сам должен следить за тем, что положил.
                                                                    Тоже такая вот экономия.

                                                                    Там есть прикол в крестах с тем, что туда нельзя класть объекты с нетривиальным деструкторами, бо хуй знает, когда их вызывать.

                                                                    Только в наш rsp по идее влезут ВСЕ объявленные переменные
                                                                    Ответить
                                                      • Ну вот ты компилятор.
                                                        Если ты в начале функции ты видишь все её перменные, то ты просто двигаешь stack pointer на нужное количество байт, и потом можешь их от него адресовывать.

                                                        Закончилась функция -- ты его обратно подвинул.

                                                        А если у тебя по ходу пьесы стек двигается на вычисляемое в рантайме количество байт (alloca, vla, или if (petuh) {int i..}, то тебе нужно как-то в рантайме понимать какого размера твой стек, и как это обратно всё потом двинуть, когда функция закочнится.

                                                        Наверное хорошо, если у тебя есть FramePointer (BP) который указывает на начало функции, от него можно хотя-бы наверное переменные адресовывать, а если нет?

                                                        Короче, написать такой компилятор труднее.
                                                        Так вижу. Но может дело и не в этом..

                                                        Алсо, стек (особенно во времена c89) было СОВСЕМ не резиновый. 16 килобайт или около того был он в паскале
                                                        Ответить
                                                        • причем тут пасцаль? это же от платформы зависит
                                                          Ответить
                                                          • Я про броланд паскаль поддос
                                                            Ответить
                                                            • max 64k минус какой-то небольшой резерв для рантайма и прорываний
                                                              Ответить
                                            • Кстати, такая вот хрень
                                              const int crap = 666;
                                              int a[crap];

                                              Клангом для Си собирается (если как глобалки), а GCC уже не хочет это собирать.
                                              Ответить
                                        • > если компилятор не докажет, что оно константа

                                          Не, в этом случае всё жёстко. Не доказал -- не скомпилил.
                                          Ответить
                                    • > Всмысле в рантайме? То есть препроцессор с условием высрет реального кода в аутпут? Не только она уровне кода замены сделает?

                                      Да. Если ты в макросне напишешь if (x) {y;} else {z;} то у тебя это условие в то место впихнется как код. Для тебя это новость?
                                      Ответить
                                      • Да, я думал сишная макросня только в компайл тайме что-то статически инлайнит в код. Но я не знаю сишки, не обращайте внимания.
                                        Ответить
                                        • > макросня

                                          Макросня работает на уровне токенов. Можешь считать её скриптом на PHP, который просто что-то там в тексте правит и копипастит. А в языке она ничерта не смыслит, ни в сишке ни в крестах.
                                          Ответить
                                          • Это-то я понимаю, просто те полтора часа своей жизни, что я имел дело с реальным кодом на си, оставили у меня впечатление, что макрос с ифом может по условию превратиться либо в один код, либо в другой, и на уровне токенов делать подмену. Про то что она умеет срать на уровне токенов реалтаймовыми условиями я не ведал.
                                            Ответить
                                            • Собственно поэтому я воспринимал a == b в коде как сравнение токенов (имён переменных), а не указателей. Иначе что это за шаблонизатор такой.
                                              Ответить
                                              • Не, там вообще всё тупо. Аргументы он может подставлять, конкатенировать и превращать в строковый литерал. В общем-то и всё. Никаких других операций над ними нет (хотя в бусте выебнулись и сделали на основе этого арифметику и функциональщину, лол).

                                                Т.е. про == и if шаблонизатор ничего не знает, как PHP ничего не знает про <div>. Поэтому он их дословно копирует на выход.
                                                Ответить
                                                • Ага, ну значит правильно ты #ifdef помянул, из-за него у меня такое впечатление и сложилось. Заебись, и он ничего не выберет, поставит как есть, а дальше уже компилятор либо оптимизнет константное условие, либо вкомпилит рантаймовое как есть. Ясно понятно.
                                                  Ответить
                                        • От вистефана не ожидал
                                          Ответить
                                          • Чего это вдруг
                                            Ответить
                                            • Ну ты же GNU/Linux пропагандируешь, должен знать как сишка работает.
                                              Ответить
                                              • Ну я не считаю, что пропогандирую, но да, сторонник. Разумеется мне стыдно не знать сишки, и я это исправлю.
                                                Ответить
                                              • может он прыщебейсик прогандирует
                                                Ответить
                          • а нельзя в крестах переопределить += у uint8_vec чтобы когда я говорю

                            a + b

                            то у a вызыавался бы append (Ну тоесть делался бы тот самый реаллок)?

                            Flexible_array_member кстати не очень нужен, когда есть шаблоны: туда же можно реальный размер передать, И потечь
                            Ответить
                            • Питухи, что не так с перегрузкой оператара то?

                              //тупой и грязный PoC
                              
                              #include <cstring>
                              #include <iostream>
                              
                              class MyVector
                              {
                              	char* data;
                              	size_t size;
                              
                              public:
                              	explicit MyVector(char l, size_t size) : data(static_cast<char*>(malloc(size + 1))), size(size)
                              	{
                              		memset(data, l, size);
                              		data[size] = 0;
                              	}
                              
                              
                              	char* Data() const
                              	{
                              		return data;
                              	}
                              
                              
                              	~MyVector()
                              	{
                              		free(data);
                              	}
                              
                              
                              	MyVector& operator+=(const MyVector& other)
                              	{
                              		int newC = data[0] + other.data[0];
                              		size_t newSize = size + other.size;
                              		size = newSize;
                              		data = static_cast<char*>(realloc(data, newSize + 1));
                              		memset(data, newC, size);
                              		data[size] = 0;
                              		return *this;
                              	}
                              };
                              
                              
                              int main()
                              {
                              	MyVector c('c', 2);
                              	std::cout << c.Data() << std::endl;
                              	MyVector q('q', 3);
                              	std::cout << q.Data() << std::endl;
                              	q += c;
                              	std::cout << q.Data() << std::endl;
                              }
                              Ответить
                              • Это не то: j123123 хочет, чтобы оно всё само.

                                > explicit MyVector
                                explicit нужен только для конструкторов, принимающих только один аргумент. Для других он ня имеет особого смысла.
                                Ответить
                                • У них по кодестайлу для всех надо писать, если вспомнить старые треды.
                                  Ответить
                                  • Какой ужас(o・_・)ノ”(ノ_<、)!
                                    Ответить
                                  • Да ежкин кот, ты опять думаешь, что я Инью?
                                    Ответить
                                    • А что, нет?
                                      Ответить
                                      • Вообще-то нет

                                        У нас нет кодстайла для крестов, потому что на крестах в моем отделе три тупых утилиты написано

                                        Я использую тот кодстайл, который форсит мне по умолчанию студия и R#, он более-ли-менее коньсистентен
                                        Ответить
                                  • Это не кодстайл, а коллега один доебывался.
                                    Ответить
                                    • > коллега один доебывался

                                      Т.е. он эту хуйню всё-таки не смог пропихнуть в кодстайл? ;)
                                      Ответить
                                      • Есть общий кодстайл для всей компании. Но ты не обязан его придерживаться, в свой проект можно коммитить любое говно. В нашем проекте 3 разработчика, и мы уже между собой договариваемся чокак, но дополнительного кодстайла у нас как такового нету, есть несколько устных договорённостей нигде не закреплённых )
                                        Ответить
                                        • У нас был срачек на работе по поводу final в жабе

                                          Я был за то, чтобы писать его во всех переменных. А другие были против.

                                          Я добавлял, другие удаляли

                                          Потом ввели общепродуктовый стиль, и разумеется ненужный final запретили

                                          Речь только о локальных (автоматических) переменных конечно

                                          А в котлине и TS "val" и "const" уже признаны хорошим тоном.


                                          А вы помечаете переменные const при любой возможности?
                                          Ответить
                                          • > помечаете переменные const при любой возможности

                                            Ну да. Читать легче.

                                            Хотя по-хорошему const на переменных должен быть по-умолчанию чтобы не замусоривать код. В ocaml'е вроде так и сделали.
                                            Ответить
                                            • Ну вот я пытался форсить это в джаве, но всех заебало читать
                                              public void doAll(final int iq, final @NotNull String name) {
                                                 final int j = 42;
                                              }

                                              Слава богу, я уже давно почти всё JVMговно пишут на котлине, а там всё неизменяемое по умолчанию, само собой
                                              Ответить
                                              • А сколько нужно усилий, чтобы взять проект на джава и начать дописывать к нему куски на котлин?
                                                Ответить
                                          • > const

                                            До этого тоже доебывается, кстати
                                            Ответить
                                            • > До этого тоже доебывается, кстати

                                              Ну про конст, имхо, есть смысл доебаться в джвух случаях где он пиздец как важен:
                                              - const справа от функции
                                              - const у данных, на которые указывают указатели и ссылки

                                              Остальное -- это просто вкусовщина и подстраховка от ошибок. Никто не умрёт, если его не напишешь. Но ревьювить будет сложнее если функция большая (надо в уме доказывать, что в переменную не срут).
                                              Ответить
                                              • > в джвух случаях где он пиздец как важен:
                                                Это же мой любимый пример отсоса всех джав и сишарпов у крестов: const семантика:)

                                                По сути это другой тип (с точки зрения джависта так точно).

                                                А внутри метода иметь немутабельные переменные просто хорошо (например tslint ругается, если ты пометишь let то, что может быть const)*.

                                                Забавно, что в котлине аргументы функции иммутабельны всегда: ты не можешь изменить то, что то тебе передали (только скопировать)

                                                * https://palantir.github.io/tslint/rules/prefer-const/
                                                Ответить
                                • Там сначала был i, потом я добавил size, и забыл удлить
                                  Ответить
                                • Нет, я приводил пример вроде. explicit ещё нужен, чтобы фигурные скобочки не работали.
                                  Ответить
    • Однако целью этого поста было передать основные шаги, не вдаваясь в детали. Давайте оглянемся назад, чтобы увидеть, сколько деталей было пропущено. Это действительно замечательно:

      - unqualified name lookup
      - argument-dependent lookup
      - member name lookup
      - template argument deduction
      - SFINAE
      - implicit conversion
      - constraints and concepts
      - ranking of implicit conversion
      - function template overloading
      Ответить
    • Что вы думаете об использовании "functional" с "algorithm"?
      Типа
      // 
      	int i[] = {1, 2, 3, 4, 5, 6};
      	int* last = std::end(i);
      	int* result = std::find_if(i, last, std::bind2nd(std::greater<int>(), 2));
      	if (result != last)
      	{
      		std::cout << *result;
      	}

      или лучше всё таки лямбду юзать и не выёбываться?
      Ответить
      • bind для одиночного вызова, лямбда для более сложных формулок. Как-то так, имхо. Короче как лучше читается -- так и пиши.

        Можешь ещё с бустом повыёбываться: std::find_if(i, last, _1 > 2).
        Ответить
      • Выёбываться вообще плохо
        Ответить
        • Почему?
          Ответить
          • Почему код на J говно? Проще понимать простой код, что твою цепочку хуйни с биндами.
            Ответить
            • > Почему код на J говно?

              Потому что ты не умеешь его читать. Я думаю с опытом он нормально воспринимается.

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

                Как и большинство коллег. Именно это я и хотел сказать.
                Ответить
                • > Как и большинство коллег.

                  А теперь представь, что вокруг тебя математики, которым эти векторные операции и функции высшего порядка гораздо ближе, чем циклы. Для них J будет читаться не хуже обычных формул.
                  Ответить
                  • Я наблюдал такое с перлом лет 20 назад

                    Для старой юниксбляди перл вполне читаем, питух с delphi бекграундом просто волосы на жопе рвет, и орет 'как вы на этом говне пишете вообще?'
                    Ответить
            • А что тут непонятного
              >std::bind2nd(std::greater<int>(), 2)
              ?
              Ответить
              • Читать очень тяжело. Надо над каждым элементом выражения задумываться, прежде чем дойдёт, что это просто x > 2.

                З.Ы. Именно за это я не люблю STL. Он пытается косплеить функциональщину, но получается как у тех папуасов с карго-культом.
                Ответить
                • Можно подумать, пиздон это лучше делает:)

                  Ну всёж таки в STL была хоть какая-то ванаби-функциональщина еще в 2003-м. А например в жабе всё руками делали
                  Ответить
                  • Нет, потому что там есть ебаная lambda. Чем lambda с двоеточием лучше стрелочной функции понять трудно, обычно таким макаром дизайнеры языка как раз помечают места, которые не предполагается сильно абьюзить. Зразу типа замечаешь, что код вербозный. То есть для питона лямбды - это так, просто чтобы было, блять.
                    Ответить
                    • Да, лямбды в питоне сделаны на отъебись

                      лист компрехеншены правда тоже лямбды в каком-то смысле (но тоже малоудобные, лол)

                      Питон такой антируби
                      Ответить
                      • Ну вот лист компрехеншоны пиздатые, это питонизм знатный. Они может и не самые удобные, зато в одном стиле с отстальным языком, заебись. Выражены теми ключевыми словами, что уже есть, без спецсимволов и йухни.
                        Ответить
                      • Компрехеншены в общем-то ничего нового не дают, разве что пару строчек на out = [] да out.append(x) экономят (ну или yield x). Это даже не функциональщина, банальный императивный цикл, немножко посыпанный сахарком.
                        Ответить
                        • Прирост производительности дают.
                          Ответить
                          • только если генератор

                            то есть круглые скобочки, а не кводратные
                            Ответить
                            • def foo(xs):
                                  return (x for x in xs if x > 42)
                              
                              def foo(xs):
                                  for x in xs:
                                      if x > 42:
                                          yield x
                              Найди 10 отличий ;) Ну нету здесь никакой функциональщины... Просто императивный код в одну строчку записали.
                              Ответить
                              • первая запись короче

                                >Ну нету здесь никакой функциональщины
                                а в map и filter есть?
                                Ответить
                                • > первая запись короче

                                  Ну тут не поспоришь.
                                  Ответить
                                  • В общем это всё говёное говно, конечно.
                                    Мне нравятся цепочки, которые есть в руби и в груви и частично в JS и в котлине и даже можно изъбнуться в перле.

                                    А только в питоне принято всё расписывать вручную, потому что цепочек нет
                                    Ответить
                                • > а в map и filter есть?

                                  Да. У тебя есть функция для одного элемента и она лифтится в функцию, которая обрабатывает много.

                                  В совсем труъ функциональщине было бы так: (map f) list, но и map(f, list) тоже неплохо её косплеит.
                                  Ответить
                                  • >Там есть функция для одного элемента и её лифтят в функцию, которая обрабатывает много.

                                    а чем вот это не это?
                                    (do_all(x) for x in list_of_petuhs)
                                    Ответить
                                    • > а чем вот это не это?

                                      Ну вот смотри, в map(do_all, list) ты описал ЧТО нужно сделать, не вдаваясь в детали реализации.

                                      А в (do_all(x) for x in list) ты пишешь КАК это нужно делать, явно выписывая императивный цикл.
                                      Ответить
                                      • то есть если бы вместо
                                        (do_all(x) for x in list)
                                        можно было написать
                                        (do_all in list)

                                        то было бы оно?
                                        Ответить
                                        • > то было бы оно?

                                          Ну это тоже не функциональщина... Где здесь превращение do_all, который обрабатывает один элемент во что-то большее, что умеет обрабатывать много? А это важно для композиции, к примеру. Чтобы я мог связать несколько таких функций в один конвейер.

                                          Как ты в твоём синтаксисе запишешь (map do_all) . (filter (> 42)) . (map preprocess)?
                                          Ответить
                                          • чем
                                            (do_all in list)
                                            отличается от
                                            (do_all, list) ?

                                            >конвеер
                                            Ну как-то так, наверное
                                            (fuck_em_all in (do_all in list))

                                            Но вообще это в питоне некрасиво сделано всё таки, что с itertools что без них.

                                            Толь дело руби
                                            # 
                                            WORDS = %w[Once there was a captain brave].freeze
                                            puts WORDS.select { |word| word.length > 3 }.map { |word| word.capitalize.reverse }.join ' '
                                            Ответить
                                            • > Толь дело руби

                                              Да, вот тут прям красиво закосплеили.

                                              Но всё равно немного не то, конечно... Нету композябельности, нельзя заюзать эти операции как лего, собирая из мелких кубиков что-то интересное.

                                              Т.е. в примере из хаскеля я могу добавить ещё какие-то фильтры и преобразования. Или даже сделать функцию, которая эти фильтры навешивает по параметрам. А потом запустить список на обработку получившейся функцией. Вот в чём суть труъ функциональщины.

                                              А в примере из руби я просто выполняю одну операцию над списком. А потом выполняю вторую. Скукотища.
                                              Ответить
                                              • Согласен. В пиздатой функциональщине с какого-то момента код сам начинает писаться под руками
                                                Ответить
                                              • ну я тоже могу собрать, а потом запустить, хотя конечно это не так красиво
                                                class Enumerator
                                                  def first_two
                                                    first 2
                                                  end
                                                
                                                  def cap
                                                    map(&:capitalize)
                                                  end
                                                end
                                                
                                                def sobral_prover(en)
                                                  en.cap.first_two
                                                end
                                                
                                                foo = %w[Once there was a captain brave].freeze.lazy
                                                bar = (0..1000).lazy.map(&:to_s)
                                                
                                                puts sobral_prover foo
                                                puts sobral_prover bar
                                                Ответить
                                                • Лол, ну вот опять у тебя строка в начале ленивой цепочки торчит. Нету композябельности ;)

                                                  Но уже очень близко...
                                                  Ответить
                                                  • так нет, тут цепочка начинается с sobral_prover

                                                    А строку туда просто пихнули, а рядом вон енумератор от 0 до 1000

                                                    Но я понимаю, что собрать конвреер, а потом его запустить было бы круче
                                                    Ответить
                                                    • > цепочка начинается с sobral_prover

                                                      Ну как это, цепочка начинается с en ;)

                                                      В принципе, можно сделать def compose(f, g) def res(x) f(g(x)) end res end.

                                                      И им уже соединять кусочки: chain = compose(cap, first_two). А потом запускать: chain foo.
                                                      Ответить
                                                      • Это называется паттерн «билдер» (stroitel).
                                                        Ответить
                                                        • > паттерн «билдер»

                                                          Да, а map -- это фабричная функция. Так и живём.
                                                          Ответить
                                                        • Не совсем

                                                          Билдер это когда ты напихиваешь говна в коробочку, а потом просишь по нему что-то построить

                                                          вот std::stringstream или StringBuilder это строители
                                                          Ответить
                                                      • ну вот TS с RxJS.
                                                        //
                                                        import {Observable, pipe, UnaryFunction} from "rxjs";
                                                        import {filter, map} from "rxjs/operators";
                                                        
                                                        const source = new Observable<number>(subscriber => {
                                                            subscriber.next(1);
                                                            subscriber.next(2);
                                                            subscriber.next(10);
                                                        });
                                                        
                                                        //создаем конвеер
                                                        function createSuperPipe(): UnaryFunction<Observable<number>, Observable<number>> {
                                                            return pipe(
                                                                filter<number>(n => n % 2 === 0),
                                                                filter(n => n > 7),
                                                                map<number, number>(n => n * 10));
                                                        }
                                                        
                                                        const myPipe = createSuperPipe();
                                                        
                                                        //прицепляем его к сурсу
                                                        source.pipe(myPipe).subscribe(console.log);


                                                        Это оно?
                                                        Ответить
                                                        • > Это оно?

                                                          Х.з., а пайпы можно закомпозить друг с другом? Или только с нуля конструктором строятся?
                                                          Ответить
                                                          • Вполне можно
                                                            //вот есть пайп
                                                            const anotherPipe = pipe(map<number, string>(n => `Num: ${n}`));
                                                            
                                                            function createSuperPipe(): UnaryFunction<Observable<number>, Observable<string>> {
                                                                return pipe(
                                                                    filter<number>(n => n % 2 === 0),
                                                                    filter(n => n > 7),
                                                                    map<number, number>(n => n * 10),
                                                                    anotherPipe); //вот я его пихнул в другой пайп
                                                            }
                                                            Ответить
                                                            • Ну вот это похоже на функциональщину... Но почему-то функции опять выглядят как инородное тело, приходится заворачивать их в пайпы.

                                                              Хотя... всё норм. pipe() это не новая сущность, просто функция для композиции функций. Ну тогда труъ.
                                                              Ответить
                                                              • Верно: внутрь pipe я могу пихнуть свою функцию, ведь filter и map это обычные функции, я могу такую же написать.

                                                                Таких функций офердохуя, кстати: есть tap для сайдэффектов, например)

                                                                Я попытался принести RxJava к нам в проект (полагаю, там тоже самое), но мне сказали юзать котлиновские корутины и ченнелы.

                                                                А там всё таки императивщина: если ты хочешь из одного ченела в другой переложить, то ты должен писать цикл (хотя он и будет конечно ленивый, ибо suspendable функция)
                                                                Ответить
                                                                • > suspendable

                                                                  Эм, а как они на JVM это сделали? Генерят класс со стейтмашинкой вместо функции? Или что-то хитрее?
                                                                  Ответить
                                                                  • Насколько я знаю, да.

                                                                    Функция это класс, хранящий в себе свое состояние и свой "стек".

                                                                    Его метод вызывает диспетчер. Метод завершается, когда встречает суспендбл вызов (разумеется, блокирующие вызовы типа read и sleep запрещены!)

                                                                    Всё это обмазано сахаром, потому выглядит как будто ты отдельный процесс запустил
                                                                    Ответить
                                            • З.Ы. Вот напиши, к примеру, чтобы реверс можно было включать и отключать. Тебе для этого придётся разорвать цепочку и въебать иф.

                                              Или попробуй написать функцию, которая настраивает фильтры, а потом отдаёт эти фильтры в другую функцию, которая уже будет обрабатывать список. Не получается, выглядит как говно? А ведь это вполне практическая задачка, на которой императивные языки просто сосут.

                                              Ты не можешь клеить куски этой цепочки во что-то более интересное, ты можешь только применять их к списку по одному за раз.
                                              Ответить
                                              • Ну да, я понимаю проблему. Собрать chain и правда трудно.

                                                Вспоминается реактивное RxJS и иже с ними. Там ты можешь создавать папйпы, как угодно их соединять, и потом куда угодно подключать.

                                                Причем это всё может быть ленивое
                                                Ответить
                                                • > RxJS

                                                  Ебучие гармошки вместо кода... Или разрабы просто не умеют его готовить?
                                                  Ответить
                                                  • гармошки это всмысле ")))))))))))"?

                                                    ну вот я там привел пример
                                                    Ответить
                                                    • > всмысле ")))))))))))"

                                                      Не, гармошка -- это те 3 экрана кода, которые до )))))))))
                                                      Ответить
                            • Лист компрехеншен тоже вроде даёт на больших листах. Замерь.
                              Ответить
                              • по сравнению с обычным фором?
                                ну может быть

                                Я обычно стараюсь генераторы, потому что они ленивы, и не создают в памяти лишний лист

                                Главное потом не пройтись по нему два раза случайно
                                Ответить
                                • Ну это понятно. Но там где надо загенерить нормальный лист, компрехеншен лучше обычных лупов. Вроде как прикол с оптимизацией аллокации памяти.
                                  Ответить
                        • Это цикл-выражение, и это заебись
                          Ответить
                          • Нкоторый момент заебательности есть в том, что там можно выразить что угодно и даже с сайд эффектом

                            но читать его не очень кмк
                            Ответить
      • std::bind — говно и ня нужен.
        https://abseil.io/tips/108
        Ответить
        • > DoStuffAsync(std::bind(&MyClass::OnDone, this));
          Но почему не
          DoStuffAsync(std::mem_fn(&MyClass::OnDone));

          ?
          Ответить
          • DoStuffAsync() нужен (Status) -> (), а mem_fn вернёт (MyClass *, Status) -> (). this-то передать как-то нядо.
            Ответить
            • да, уже туплю ночью.

              DoStuffAsync же не имеет this

              Но я всё равно не понимаю, на что расчитывали seasoned C++ engineers пися
              > std::bind(&MyClass::OnDone, this)

              что this как-то волшебным образом прибайндтися к OnDone?
              Ответить
              • А оно и прибиндится. У крестовых функций высшего порядка есть перегрузки для указателей ня методы, так что и bind, и invoke, и apply прекрасно понимают this.
                struct X {
                    int x;
                    void foo()
                    {
                        std::cout << "X(" << x << ")::foo()" << std::endl;
                    }
                
                    std::function<void()> get_callback()
                    {
                        return std::bind(&X::foo, this);
                    }
                };
                
                int main()
                {
                    auto x = X(16);
                    auto f = x.get_callback();
                    f();
                }
                Ответить
    • сук )
      https://i.redd.it/mleiaj2hucg31.png
      Ответить
      • Выглядит как фейк. Само приложение ведь никак не участвует в получении пуша? Не мог же Эппл так обосраться, либо специально отправили такой текст.
        Ответить
        • Дык отправку пушей инициирует не эппл, а какой-то сервак от разрабов приложения. Вот в нём поди и косяк с обработкой ошибок.
          Ответить
          • сервак был на пхп, и выдал ошибку в stdout
            Ответить
            • Не, там бы тогда про mysql рассуждалось.
              Ответить
              • Can't connect to the server localhost in /home/s/wekspir/tsitata/index.php at line 979

                Уильям Шекспир
                Ответить
        • Нотификацию может выдать и само приоложение. А оно может получать пуш от эппла или переодически чего-то запрашивать в фоне и рисовать нотификаций

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

          Там ios нас будило, и мы рисовали нотификацию.

          Но как именно работало уже не помню, давно очень было(
          Ответить
          • > пуш эппловский не использовался
            > можно пулить прямо с сервера

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

              Лол, я нашел репу с тем говном)
              Там было так:
              UIBackgroundModes -> fetch стояло в Info.plist, и потом ios переодически нас будила, и дергала performFetchWithCompletionHandler

              ну мы фетчили по http и создавали UILocalNotification
              Ответить
              • Х.з., у меня нет опыта с айфонами. Но я не думаю, что там прям сложная процедура. Всяко не сложнее заливки в аппстор.

                Пуши сейчас даже в браузерах есть. И юзать их вообще тривиально.
                Ответить
                • То приложение было не для апстор, оно было интерпрайзное, и деплоилось с локлаьного сервера.

                  А вот подпись для него нужно было получать официально. Платили бабла эпплу, и их эппла звонил питух, и подтверждал!

                  Пишут, что можно зайти в свой девелопре аккаунт на эппле и зарегить там пуш

                  Пуши в браузерах ты сам делаешь со своего сервера же, нет "централизованного сервера пушей"
                  Или есть?
                  Ответить
                  • > Или есть?

                    Вроде есть. Иначе у тебя браузер заебётся поллить десяток сайтов.
                    Ответить
                    • В том проекте были нотификации в браущзере кстати, но тоже локальные
                      Ответить
            • Ну они правда ещё собирают все твои пароли, смс, состояние банковского счета сбербанк онлайн, парсят все что могут, и хранят в гугле или эпл, но вообще да, они экономят батарейку. А ещё иногда падают или приходят неадекватно поздно.
              Ответить
              • Ну это уже проблема конкретных приложений... Никто их не заставляет конфиденциальные данные передавать прямо в пуше.
                Ответить
                • А может и да.
                  Ответить
                • Заставляет, смс я могу получить и на нокиа 3310, и он меня уведомит. Я не уверен до конца, но что-то мне подсказывает, что современное ведро, чтобы издать бздыньк по приходу смс и показать пуш, прогонит хотя бы его урезанный до многоточия текст через гугл сервис.
                  Ответить
                  • Ну там даже в доке об этом пишут: "хочешь end-to-end, чтобы гугл не читал? можешь зашифровать, вот тебе примеры библиотек".

                    А разрабам похуй, конечно. Отправляют плейнтекстом.
                    Ответить
                    • А приложение умеет без пуш-сервиса просто слать в ведре уведомления? Можно и без енд ту енд, можно вообще не слать ничего никуда, а просто показать уведомление, ведь инициатором-то пуша является часто само твоё же локальное приложение. но гугл с этим борется, насколько я знаю. Чтобы не было нежелательных уведомлений.
                      Ответить
                      • Я не очень тебя понял

                        Ты хочешь локально нотификацию показать? Типа висишь сервисом и показываешь Toast?
                        Ответить
                        • Типа того, но это как раз и упрется в батарейку, я понял
                          Ответить
                          • Ну да, если ты будешь сервисом в фоне работать, то ты будешь поёбывать батарейку
                            Ответить
                            • > поёбывать батарейку

                              Кстати, фетч про который ты выше пишешь, это же тоже походу оптимизация батарейки? Чтобы твой сервис ходил в инет только в положенный таймслот вместе со всеми остальными, а потом девайс нормально спал с отключенной сетью.
                              Ответить
                              • Если я верно помню, то да:

                                Я прошу ios иногда меня разбудить, чтобы я мог что-то пофетчить.

                                Иос имеет право не будить меня когда нет батарейки, или когда там дорогой Интернет в роуминге

                                Но возможно этот API уже устарел.

                                А в андроиде есть WorkManager , который ты тоже можешь попросить чтобы тебя запускали только когда телефон заряжен или есть wifi итд
                                Ответить
                                • > когда телефон заряжен или есть wifi

                                  Ну это для каких-то больших загрузок, наверное. Когда какая-нибудь игрушка или навигатор хочет скачать гигабайт. Ради сообщений в мессенджере было бы глупо ждать вайфая.
                                  Ответить
                                  • Слышал байку, как у чувака по роумнигу в другой стране операционка обновилась на телефоне
                                    Ответить
                                    • У меня так месячный лимит трафика за день просрался... Сначала убунта обновилась, потом винда, потом стим решил игрушки обновить. Х.з. как народ на мобильном инете сидит.
                                      Ответить
                                      • ЗА ГРАНИЦЕЙ

                                        (тру стори)

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

                        Эм, да может конечно. У меня даже говнотифи так делало... Борьба с этим очень простая: тычешь в уведомление и говоришь "больше не показывать". И приложение с этим запретом ничего сделать не сможет.

                        А пуш -- это именно про оптимизацию доставки небольших пакетов от сервера. Ну и если тебе совсем влом пилить сервис -- можешь попросить, чтобы ось сама его показала когда получит. Тут, конечно, шифровать ты его не можешь иначе как ось без твоей помощи покажет.
                        Ответить
                        • Ну ладно, тогда ок пока, тогда разрабы действительно ссзб
                          Ответить
                          • Смски кстати идут через вендора только если оба телефона от него и интернет есть. От банка скорее всего по-нормальному через опсоса придёт, как на кнопочном.
                            Ответить
    • Разбудите меня через 150 лет, и спросите, что делают на говнокоде.
      И я отвечу: обсырают С++.

      Прежде, чем обсирать его, переведите на няшную такую вот ненужную программу, написанную в терминах C++03 (а то и 98)
      /// Количество строк не многим больше, чем в питоне
      
      #include <iostream>
      #include <algorithm>
      #include <iterator>
      #include <vector>
      #include <string>
      #include <functional>
      #include <ostream>
      
      int main()
      {
      	setlocale(LC_ALL, "Russian");
      	const std::istream_iterator<std::string> s(std::cin);
      	std::vector<std::string> words(s, std::istream_iterator<std::string>());
      	std::sort(words.begin(), words.end());
      	words.erase(std::unique(words.begin(), words.end()), words.end());
      	std::reverse(words.begin(), words.end());
      	for (std::vector<std::string>::iterator i = words.begin(); i != words.end(); ++i)
      	{
      		std::transform(i->begin(), min(i->end(), i->begin() + 2), i->begin(), toupper);
      		std::cout << *i << std::endl;
      	}
      }
      
      ///////
      C:\Users\MAKAKA>echo мы ебали медведя бля буду буду бля | "makaka.exe"
      МЫ
      МЕдведя
      ЕБали
      БУду
      БЛя


      Не то чтобы подобные задачи я решал на работе, но это показывает, как много всего можно было делать из коробки еще 20 лет назад.

      PS:
      Текст взят отсюда:
      https://www.youtube.com/watch?v=cBdIsUp6k7o
      Ответить
      • Для начала перепиши это все на крестах без крестовой стдлибы. Или ты считаешь валидным аргумент типа "язык X лучше языка Y потому что в языке X в стандартной библиотеке реализована хуйня для Z, а в языке X такой хуйни не реализовано"?
        Ответить
        • Стандартная либа крестов круче стандартной либы сишки, это твёрдый факт!
          Ответить
          • Сишка это вообще не про "куча хуйни в стандартной либе", там как раз специально избегали добавлять кучу хуйни.

            Когда Ричи хотел внести в C очередную фичу, Керниган говорил: "Если тебе нужен PL/1, ты знаешь, где его взять". Видимо, Страуструп не знал, где взять PL/1.
            Ответить
            • Именно поэтому там можно разобрать время как в локальной таймзоне, так и в утц, а обратно собрать можно только в локальной?

              Какая ортогональность ))
              Ответить
            • Угу

              А потом в каждом серьезном проекте ..

              these subsets (сишные) are buried under an abstraction layer that contains about 50% of all Postfix source code, and that provides the foundation on which all Postfix programs are built. For example, the "vstring" primitive makes Postfix code resistant to buffer overflow

              Сишке действительно не нужно иметь в стандартной библиотеке парсер XML, но писать одно и тоже в каждом проекте тоже не айс.

              -------

              Вообще какие есть варианты?

              1. Насрать всё стандартную либу, и стать непереносимым.
              2. Ничего не иметь в стандартной либе, писать всё с ноля, и ебанутьчся
              3. Ничего не иметь в стандартной либе, сделать репу с "хорошими решениями" и стать "leftpad".

              Кажется, все три варианта самые плохые
              Ответить
          • И что характерня, даже в стандартной либе сишки лучше сделана работа со строками, чем в std::string.
            Ответить
            • А в питоне строки ещё лучше. Это тоже твёрдый факт!
              Ответить
        • > Или ты считаешь валидным аргумент
          А это зависит. Для высокоуровневых скриптовых языков такой аргумент вполня себе валиден, потому что чем больше говна в стдлибе — тем проще и быстрее няписать говноскриптик, а скорость и простота няписания говноскриптиков — один из важных параметров скриптоязыка.
          Вот у ме-ня возникла нядавня задача вытащить инфу из виндовых инсталляторов (которые msi). Я взяла Python, импортировала msilib и решила свою задачу за десять минут: максимальня быстро и безо всяких поисков нужных либ. Это хорошо и удобня.
          Ответить
        • >Для начала перепиши это все на крестах без крестовой стдлибы.

          Зачем? Зачем писать на крестах без стдлибы?
          Ответить
          • > Зачем? Зачем писать на крестах без стдлибы?

            Не всегда есть выбор ;(

            Она, к сожалению, неудачно спроектирована и слишком сильно завязана на сервисы ОС.
            Ответить
            • Ты про окружения, в которых она не работает?
              Ответить
              • Ага. Причём если в gcc с горем пополам можно хотя бы исключения и глобалки привернуть, то в студии это надо будет реверсить и пилить вручную.
                Ответить
                • Ну блин, чем сложнее либа -- тем хуёвее портируется, это понятно.


                  Вот lua везде работает, на любом C89 компиляторе.
                  Ответить
      • > std::transform(..., toupper).

        Удачи с более сложными языками. Один из самых наивных факапов в дизайне крестострок.
        Ответить
        • Да понятно, что я сосну если там будет не wchar, а не char.
          Причем оно же, суко, может и скомпилироваться.
          Ответить
          • Да ты и с wchar'ом соснёшь из-за какого-нибудь немецкого... И вообще это сишная функция, которая возвращает int (!).
            Ответить
            • В int стандартного размера отлично влезает UTF-32. Нафиг однобайтные кодировки, нафиг переменную длину. В std::vector<int> влезет любая строка.
              Ответить
              • Влезть то она влезет... Но из-за ебанутых правил некоторых языков апперкейсить её ничуть не проще, чем мультибайтовый утф-8.
                Ответить
              • З.Ы. Можешь глянуть у меня в профиле лабу на тему "сформировать строку из слов исходной строки, содержащих повторяющиеся буквы".
                Ответить
            • почему сосну если локаль поставлю?

              С русским не соснул же, чем немецкий хуже?
              Ответить
              • Там какая-то засада с straße -> STRASSE. Длина строки меняется, в общем.
                Ответить
                • лол, да: с лигатурами можно соснуть.

                  а ща проверю
                  Ответить
                • так тут надо сказать соснет и сишечка, да)


                  Вообще настоящие строки должны содержать кодпоинты наверное, а не байтики
                  Ответить
                  • Да без разницы, на самом деле. Ты и с кодепоинтами эту задачу не решишь...

                    Просто не надо напяливать transform на строки, вот и всё. Им нужны свои алгоритмы и итераторы, как в том же icu.

                    А utf-8, utf-16, utf-32, какая-то другая кодировка -- это вообще непринципиально.
                    Ответить
                    • В юникоде есть всякие модификационные символы типа
                      https://codepoints.net/U+00B4

                      То есть ситуация, когда при добавлении символа не изменяется их число, а просто меняетя предыдущий, там в порядке вещей.

                      Твой эсцет из той же области

                      Вот что я имел ввиду)

                      Но ты прав: работать с такими строками как векторами каких-то сущностей уже не получится


                      зы: всем хватит cp866 или koi8-r. Понапридумывали хуйни ненужной, блядь
                      Ответить
                      • > как векторами

                        Получится, но надо stateful алгоритмы. А transform он без состояния.
                        Ответить
                        • Как всё сложно:-/

                          Всё таки крестостроки это такие обёртки вокруг массива чаров (точнее того, что там в traits), вообще почему они не спецификация вектора?:)

                          "настоящие" строки это совсем другое, ну вот icu наверное для того
                          Ответить
                          • > почему они не спецификация вектора

                            Так вышло. Они же в крестах были изначально, задолго до STL. Ну и нолик там в конце, как в соседнем треде обсуждали.

                            > icu наверное для того

                            Угу. Оно и весит десятки мегабайт...
                            Ответить
      • > words

        Удачи там с японским. В icu походу мегабайтный словарь японских слов для этого есть.
        Ответить

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