Здравствуйте, kov_serg, Вы писали:
A>>Я тут вычитал идею писать на связке PHP и C++. С каждым днём она кажется мне всё менее безумной. A>>Впрочем, наверно, вместо PHP можно взять и что-то получше, да? PHP же не позволяет развернуть #pragma once в гарды? Как там реализовать конструкцию "добавить в конец файла"?
_>Еще вариант lua + c
Я не сталкивался с Lua, но он же вроде для ембеддинга, а не для препроцессинга?
Идея в том, чтобы писать макросы типа is_in_set на внешнем языке (типа PHP), пропускать через процессор (например, через pre build steps), он их будет разворачивать в нужное количество сравнений, а затем результат подавать на вход компилятору.
Только вот не уверен я, что код будет выразительнее, чем с дефайнами.
Кроме того, если мы захотим генерировать заголовочные прагма-гарды (#ifndef #define ... #endif) вместе с #pragma once или ИЗ #pragma once, вроде бы, похапе так не может, для этого надо уметь добавлять в конец, даже если там нет тега <? >, да ещё и по-умному, чтобы не было пересечений. Это не самая практичная задача, а просто пример того, что язык и его процессор должны уметь делать.
Здравствуйте, Евгений Музыченко, Вы писали:
_>>если C++ будет не совместим с C, то он потеряет интерфейс к внешнему миру
ЕМ>Про совместимость по ABI я вообще не говорю — без нее как раз нельзя. Я исключительно про совместимость с C по тексту программы.
Ну вот я пишу сейчас прошивку для микроконтроллера nRF. У них SDK на C. Примеры на C. В принципе я и пишу на C, но в целом почему бы мне не писать на C++, если очень хочется. Думаю, многие пишут. При этом у них в хедерах и inline функций хватает, и макросы вовсю используются. Тут текст от заголовка уже так просто и не отличить.
Здравствуйте, kov_serg, Вы писали:
_>Вообще-то надо более вменяемый язык, чтобы он не вызывал столько неоднозначностей и имел возможность явно указывать что можно оптимизатору додумывать, а что нет.
Язык-то зачем? По-моему, в плюсах в целом и синтаксис, и семантика вполне человеческие, за исключением отдельных крайних случаев, которые, при желании, можно постепенно выправить. Вполне достаточно поверху навесить — где атрибуты, где прагмы, а где можно и конструкции вроде паскалевских "управляющих комментариев".
_>>>что бы собрать исходник, надо самый свежий компилятор ЕМ>>Это где такое? _>В линухах
Ну, тамошняя мода непременно таскать все в исходниках, и собирать по месту, вообще крайне странна, если не сказать сильнее.
_>VStudio 2023
Имеете в виду 2022?
_>не ставиться на семёрку.
Да и хрен бы с ней. В студиях навороченные отладчики — скорее всего, там что-то завязано на свежие десятки. Имеет право.
Компиляторы, линкеры и прочие build tools из 2022 отлично работают под семеркой. Подозреваю, что будут работать даже под 2k, если версию в PE поправить. Чего б им не работать, коли это, по большому счету, командно-строковые преобразователи файлов.
_>Компилятор по умолчанию генерит код который не семёрке может не работать.
Компилятор никогда не генерил системно-зависимого кода. Все системные зависимости — в стандартных библиотеках. Самым свежим компилятором/линкером от VC++ можно делать EXE/DLL хоть под Win95, только версию в PE придется править, линкер не дает поставить subsystem меньше 5.0.
_>Браузеры 7ку тоже не поддерживают, даже питон и пхп не семёрке не пускаются.
УМВР ЧЯДНТ?
_>Фаза синтеза кода нужна для выбора реализации в условиях заданных ограничений, подбора контейнеров и трансформации алгоритмов и т.п. без онанизма в виде шаблонных городух и будующей рефлексии.
Зачем для этого нужна непременно фаза синтеза? Что мешает ввести любые адекватные конструкции для управления имеющимся механизмом? И рефлексию так же. Например, рассматривать каждую сущность (значение, тип, объект, функцию, параметр шаблона, сам шаблон и т.п.) как псевдообъект с набором свойств. Что-нибудь вроде __props(f).name — имя функции, __props(T).type — тип параметра T, и так далее. В любом мало-мальски удобном виде, лишь бы было.
_>Это следствие того что на макросы забили и решили их не развивать, но выкинуть не могут ибо без них никак.
Нет никакого смысла развивать макросы, которые обрабатываются, как тупые текстовые фрагменты. При таком подходе даже простые решения быстро упираются в невозможность генерации кода иначе, как простой текстовой подстановкой.
_>Нет это приводит к тому что под капотом этих библиотек страх и ужас.
Я именно так и выразился, почему нет-то?
_>Нет при правильном подходе C++ был изначально просто сменной надстройкой над C. И вообще-то никто не мешает использовать разные надстройки.
Я в упор не понимаю, для чего ему быть "надстройкой". Когда Win95 была "надстройкой" над досом, это хоть кому-то нравилось?
Здравствуйте, Alekzander, Вы писали:
A>Идея в том, чтобы писать макросы типа is_in_set на внешнем языке (типа PHP), пропускать через процессор (например, через pre build steps), он их будет разворачивать в нужное количество сравнений, а затем результат подавать на вход компилятору.
Ну сделаете Вы так, а дальше-то что? Задача ж сугубо частная, не так уж много задач можно решить таким образом, чтоб вся эта возня окупилась. Если уж делать механизм, то более-менее универсальный.
A>Это не самая практичная задача, а просто пример того, что язык и его процессор должны уметь делать.
В том-то и дело, что подобные решения всегда будут лишь частными. Чтоб можно было делать удобные и эффективные решения для разных задач, язык должен, с одной стороны, позволять извлекать из компилятора информацию о компилируемой программе, а с другой стороны — применять эту информацию для порождения других элементов программы.
Здравствуйте, vsb, Вы писали:
vsb>При этом у них в хедерах и inline функций хватает, и макросы вовсю используются. Тут текст от заголовка уже так просто и не отличить.
Так я и говорю, что подобные фрагменты можно было бы явно отмечать режимом совместимости, а не держать этот режим для всего по умолчанию.
, как написать в плюсах is in set.
ЕМ>Тут нужно начать с того, что задача именно в таком виде не является достаточно типовой, чтобы иметь в языке какие-то свойства именно под нее.
Во-первых.
Я привёл пример на тему, когда пишущий на C++ прибегает ко встроенному Си, и почему. Эти примеры я могу приводить и дальше, а этот выбрал потому, что он рядом, в этом же форуме, его все видели, и настоящие эксперты (не то, что я) привели какие-то решения, высоко оценённые другими экспертами.
Во-вторых.
Этот пример достаточно типовой, чтобы его привёл автор исходной статьи, тот который из PVS. То есть, это вообще не мой пример. Мой вклад тут в том, что я переформулировал задачу исходя из интересов программиста, а не компании PVS.
Маленький оффтопик. Я тут читал статью про лечение ВИЧ. Есть несколько случае полного излечения, когда следов вируса не обнаруживается много лет. Но медицина в эту сторону не копает. Знаешь, почему? Официальный ответ: это не нужно. Пока ты принимаешь антиретровирусную терапию, ты будешь здоров (не разовьётся СПИД, не сократится жизнь и т.д.). То есть, ты здоров, пока работаешь кошельком для фармацевтов. Удобно, да? Врачи не очень заинтересованы в том, чтобы люди были здоровы. Они заинтересованы в том, чтобы люди лечились.
Вот и авторам статических анализаторов не нужно, чтобы ты писал здоровый код. Ведь тогда анализаторы перестанут находить у тебя ошибки, а ты перестанешь их покупать. Поэтому, увидев совет пользоваться форматированием (которое особо не спасает), я переформулировал эту задачу так: в каком виде надо записывать такие сравнения, чтобы эта ошибка стала невозможной? Как выработать здоровую привычку для здорового кода? Такую, как Йода-сравнения, например. Вот и всё. А сама ошибка достаточно типовая, чтобы автор PVS её рассмотрел в своей статье.
Надеюсь, теперь понятно, откуда взялась задача именно в таком виде. Это хороший вид, полезный.
ЕМ>По-хорошему, шаблоны должны быть обобщением на всё, что может потребовать шаблонной обработки, включая генерацию статических таблиц данных во время компиляции. И они должны быть интерфейсом не к препроцессору, а полноценным элементом языка, с адекватными возможностями управления.
Шаблонизация должна быть обобщением на всё, что может потребовать шаблонной обработки. А конкретно template это один из инструментов шаблонизации. Изначально он вообще весь был вокруг typename. Его раздули до недопрепроцессора, а других инструментов шаблонизации не дали (ну и остались устаревшие инструменты из Си). Но мне лично это не кажется правильным. Почему? Да потому, что приведённая в пример задача этим инструментом, как я понял, не решается. Чтобы не начинать заново, типичная она или нет, я сразу скажу, что миллион таких задач приведу.
A>>Очевидное условие — отсутствие паразитного call'а, потому что если ты на него согласен, хватит и простой перегрузки функций.
ЕМ>inline не спасает?
The original intent of the inline keyword was to serve as an indicator to the optimizer that inline substitution of a function is preferred over function call, that is, instead of executing the function call CPU instruction to transfer control to the function body, a copy of the function body is executed without generating the call. This avoids overhead created by the function call (passing the arguments and retrieving the result) but it may result in a larger executable as the code for the function has to be repeated multiple times.
Since inline substitution is unobservable in the standard semantics, compilers are free to use inline substitution for any function that's not marked inline, and are free to generate function calls to any function marked inline. Those optimization choices do not change the rules regarding multiple definitions and shared statics listed above.
То есть, и раньше ничего не гарантировалось, а теперь и подавно.
Тут дело такое. Оптимизаторы массово посходили с ума, и творят страшные вещи. Это касается теперь и Си, к сожалению. А значит, они могут и для явно записанных пар сравнений сгенерировать функцию и её вызов. Я считаю, что чтобы с этими волками жить, надо по-волчьи выть. А именно, писать тот код, который максимально чётко показывает, что ты хочешь. И если оптимизирующий компилятор сделал что-то, чего ты не хочешь, надо ругаться с автором компилятора. Так делает Линус, так делают разные программисты из статьи, на которую я дал ссылку.
А если ты явно описываешь функцию, пусть даже помеченную inline, то ругаться уже бесполезно. Тебя ткнут носом в стандарт, и спросят, на что ты жалуешься.
A>>Альтернативой был бы нормальный препроцессор, а не говно мамонта из языка Си.
ЕМ>Адекватной альтернативой был бы не препроцессор, с его сугубо текстовыми параметрами/подстановками, а нормальные средства условной компиляции. Чтоб шаблон мог узнать у компилятора любые подробности любого из своих параметров, включить в порождаемый код любой из своих элементов в зависимости от условия, если параметров переменное количество — наглядно перебрать их в конструкции вроде "псевдоцикла", работающего во время компиляции, на любом этапе вывести сообщение, и т.п. Примерно так работают классические макропроцессоры.
Это уже спор о терминах. Я имел в виду именно это.
A>>Выше уже написали: попробуйте, если такие смелые. Посмотрим, сколько на нём программистов останется.
ЕМ>Ну вот Вы бы ушли с удобного в целом языка лишь потому, что его компилятор по умолчанию стал выдавать множество предупреждений (которые, если их внимательно прочитать, чаще всего спасают Вас от вероятных косяков, нежели просто надоедают из вредности), любое из которых, или даже все вместе, можно подавить пометками в тексте программы или ключами компилятора?
Я подозреваю, это вопрос из серии "Вы любите тёплое пиво и потных женщин?" с последующим отпуском в ноябре. Конечно же, ответ будет — смотря о чём речь. Кастинги мне нужны как в Си, точка. По очень многим причинам, я их не буду здесь перечислять. Если "пометка в тексте программы" это X_cast<T>, то неважно, что об этом думаю я, это будет конец паразитированию на Си и, как я сильно подозреваю, конец мифу о популярности C++.
A>>Нахера мне нужен язык с ручным управлением памятью, если в нём кастинг и инициализация работают не как в Си?
ЕМ>Вот сейчас вообще не понял. Какая между этим связь? Это ж совершенно ортогональные друг другу вещи.
Какие ты привёл примеры ("столь же "молчаливая" обработка C-style cast, определение неинициализированных переменных без нужды и подобное"), на то я и ответил.
Другое дело, что и Си уже не тот. Си теперь тоже дофига высокоуровневый.
A>>Создатели плюсов поступили очень умно, решив, вот именно, ПАРАЗИТИРОВАТЬ на Си. Если бы они сделали всё то, что ты предлагаешь, у них бы получилось что-то типа D. То есть, дико популярное, но только в очень узких кругах.
ЕМ>По-Вашему, большинство голосишников — маргиналы, стремящиеся уйти от любого контроля только потому, что это контроль, и он теоретически может ограничить их личную свободу?
Не знаю, как большинство (или там сиплюсплюсные меньшинства), а я смотрю на ситуацию так. Есть два разумных варианта: или виртуальная машина (CLR, JVM, V8 и т.п.) и гарантия отсутствия проблем с памятью, или ответственность на мне, но я должен понимать, что происходит, и контролировать ситуацию. Если я объявил переменную, но не проинициализировал, значит под неё выделилась память, и она содержит всякую фигню. Всё, дальше я сам. Если я что-то делаю с указателем, то делаю что-то с указателем. Иначе возникает ситуация, когда компилятор меня ограничивает, но ни за что не отвечает.
Ещё раз: это, к сожалению, в полной мере применимо и к старому доброму Си, как его теперь видят зумеры. Это не эксклюзивно проблема С++.
Здравствуйте, Евгений Музыченко, Вы писали:
A>>Для is is set тоже нужно обобщение на типы. Но это второстепенная задача. Главное там — генерация произвольного количества сравнений.
ЕМ>Если элементов (идентификаторов) не больше, чем количество разрядов в машинном слове, то сравнения вообще не нужны. Нужно преобразовать проверяемое значение в битовую маску, и с помощью команды типа test проверить, входит ли она в множество, образованное совокупностью представленных элементов. Множество (битовая маска) вычисляется на этапе компиляции. Если проверяемое значение заведомо не может быть вне множества, то не нужны даже предварительные сравнения на больше/меньше.
Мне кажется, оптимально остановиться на преобразовании в ==. Исходная задача была в том, что по ошибке вместо результата сравнения использовалось само значение, и с этим надо что-то делать. В общем случае заранее неизвестно, какой там тип и во что выльется ==.
Здравствуйте, Евгений Музыченко, Вы писали:
A>>Идея в том, чтобы писать макросы типа is_in_set на внешнем языке (типа PHP), пропускать через процессор (например, через pre build steps), он их будет разворачивать в нужное количество сравнений, а затем результат подавать на вход компилятору.
ЕМ>Ну сделаете Вы так, а дальше-то что? Задача ж сугубо частная, не так уж много задач можно решить таким образом, чтоб вся эта возня окупилась. Если уж делать механизм, то более-менее универсальный.
Так это и есть универсальное решение.
Кагбе сказать... Вот конкретно начать писать на пыхе плюсовые программы, это я пока всерьёз не рассматриваю. Но всё же тут есть здравое зерно. Оно в том, что мне не нравится, во что превращается язык (и давно превратился). Взять другой ЯП я не могу, т.к. их нет. Написать свой я тоже не могу, т.к. я ваще не умею писать языки прикладник. Да и глупо это. Кто мне за такое заплатит.
Но можно потихоньку писать макросы на верхнем языке просто по мере написания прикладного кода. Я и раньше писал всякие библиотеки, в т.ч. библиотеки макросов. Получится такой квазиязык.
A>>Это не самая практичная задача, а просто пример того, что язык и его процессор должны уметь делать.
ЕМ>В том-то и дело, что подобные решения всегда будут лишь частными. Чтоб можно было делать удобные и эффективные решения для разных задач, язык должен, с одной стороны, позволять извлекать из компилятора информацию о компилируемой программе, а с другой стороны — применять эту информацию для порождения других элементов программы.
Оно не частное, а общее.
Частный тут только пример. Не могу вспомнить, откуда он, с этого форума, или на Хабре видел, или ещё где, но вот недавно совсем обсуждался вопрос с гардами, какой-то там компилер, как оказалось, без них не может. И спрашивается, как жить. Таскать и прагму, и гарды? А я взял и обобщил: нужна вставка в произвольные места, со стеком, чтобы разруливать вложенности. Если это делать через препроцессинг, конечно.
Здравствуйте, Alekzander, Вы писали:
A>когда пишущий на C++ прибегает ко встроенному Си
Это бессмысленная формулировка. Нет в C++ никакого "встроенного Си" — есть только конструкции, "унаследованные от C", "совместимые с C" и т.п. Иначе придется признать, что использование любых фундаментальных типов (кроме bool), и любой арифметики над ними, операции присваивания, точки с запятой и прочего — это "прибегание ко встроенному Си".
И даже говорить, что используются приемы "в стиле C" или "в парадигме C" тоже бессмысленно, ибо сам по себе C++ никаких определенных стилей/парадигм не предполагает.
A>этот выбрал потому, что он рядом, в этом же форуме, его все видели, и настоящие эксперты (не то, что я) привели какие-то решения, высоко оценённые другими экспертами.
Я бы сказал, что в вашем обсуждении народ просто развлекался для разминки мозгов. Одни это любят, другие не понимают. Я вот тоже считаю, что напрягаться для решения задачи имеет смысл, когда задача возникла более-менее естественным путем, а не когда ее создали искусственно. В жизни и так хватает задач, которые возникают сами собой, чтобы отвлекаться еще и на решение специально созданных — напоминает анекдот про гамак и лыжи.
A>Этот пример достаточно типовой, чтобы его привёл автор исходной статьи, тот который из PVS.
Насколько я понял, он как раз не типовой, а всего лишь показательный. Где подобные длинные цепочки сравнений можно увидеть в товарных количествах?
A>медицина в эту сторону не копает. Знаешь, почему? Официальный ответ: это не нужно.
Это Вы теорий заговора начитались. Медицина в эту сторону копает с 80-х — то есть, со времен, как только вирус был выделен. Но все прогнозы пока неутешительны. Даже с вирусом простого герпеса, который куда сильнее локализован, пока справиться не могут — слишком сложно.
A>Пока ты принимаешь антиретровирусную терапию, ты будешь здоров (не разовьётся СПИД, не сократится жизнь и т.д.).
Угу, а когда у тебя (или у твоего государства) нет денег на достаточное количество препаратов, ты не принимаешь АРТ. И все, у кого тоже нет денег (или кого не смогли заставить), тоже не принимают. Но они (внезапно) не берут на себя обязательства поддерживать строгий моральный облик, и активно участвуют в распространении вируса.
С тех пор, как стало понятно, что СПИД — это не просто болезнь, а пандемия, главной задачей стало сдерживание ее распространения, а отнюдь не продление жизни инфицированных. С точки зрения любого государства, было бы гораздо удобнее, чтобы инфицированные умирали как можно быстрее, успевая заразить как можно меньше других. Вот тогда мировая фарма действительно особо не напрягалась бы с поиском способов лечения.
A>Врачи не очень заинтересованы в том, чтобы люди были здоровы. Они заинтересованы в том, чтобы люди лечились.
Вы путаете врачей с "психологами", "психотерапевтами", "целителями" и подобными. Даже в платном медцентре типичный врач не станет умышленно затягивать лечение конкретного пациента, ибо вновь заболевших всегда в достатке. А типичный врач в поликлинике все равно не заработает больше, если пациент придет к нему десять раз вместо трех. Наоборот — он предпочел бы, чтоб пациент не приходил даже во второй раз.
A>Вот и авторам статических анализаторов не нужно, чтобы ты писал здоровый код. Ведь тогда анализаторы перестанут находить у тебя ошибки, а ты перестанешь их покупать.
Судя по активности рекламы того же PVS-Studio, его не очень-то покупают. Я, например, этими анализаторами вообще не пользуюсь.
A>каком виде надо записывать такие сравнения, чтобы эта ошибка стала невозможной?
"Ни в каком, бл#! Теперь — в твердом переплете".
A>Как выработать здоровую привычку для здорового кода? Такую, как Йода-сравнения, например.
В таких привычках нет ничего здорового. Это просто очередной кривой костыль, на безрыбье. С тех пор, как компиляторы начали выдавать предупреждения на потенциально опасное присваивание (где-то с 90-х, если не ошибаюсь), это задомнапередное сравнение полностью потеряло смысл.
A>Надеюсь, теперь понятно, откуда взялась задача именно в таком виде. Это хороший вид, полезный.
ЕМ>>По-хорошему, шаблоны должны быть обобщением на всё, что может потребовать шаблонной обработки, включая генерацию статических таблиц данных во время компиляции. И они должны быть интерфейсом не к препроцессору, а полноценным элементом языка, с адекватными возможностями управления.
A>Его раздули до недопрепроцессора
Что значит "до недопрепроцессора"? Любой препроцессор в ЯВУ — по определению убогий костыльный инструмент, применяемый от безысходности, когда нет ресурсов делать адекватный анализатор/генератор кода, а работать надо. Что сишний, что плюсовый — яркие примеры принципа "нет ничего более постоянного, нежели временное".
A>а других инструментов шаблонизации не дали (ну и остались устаревшие инструменты из Си). Но мне лично это не кажется правильным.
По-моему, это не кажется правильным любому, для кого жонглирование побочными эффектами шаблонов не является самоцелью. Особенно тем, кому доводилось видеть, или хотя бы воображать, более адекватные инструменты.
A>потому, что приведённая в пример задача этим инструментом, как я понял, не решается.
Как и многие другие, куда более актуальные. Хотя даже не сомневаюсь: если заинтересовать ею "шаблонных хакеров" во главе с Александреску, Степановым и иже с ними, через некоторое время они родят внешне приемлемое решение, но вот реализацию его будет лучше не смотреть на ночь.
A>Оптимизаторы массово посходили с ума, и творят страшные вещи. Это касается теперь и Си, к сожалению.
Подобные тексты советую читать с изрядной долей скептицизма. Их авторы традиционно путают особенности реализаций, которые зачастую бывает удобно и полезно использовать именно для конкретных платформ, с условной "С-машиной", которую описывает стандарт. Они хотят странного — чтоб стандарт одновременно обеспечивал и неограниченную переносимость, и предельную эффективность любой конкретной реализации, и чтоб нигде не возникало UB. А это принципиально невозможно — либо абстракция, либо конкретика, третьего не дано.
Собственно, унихоиды сами загнали себя в эту ловушку, поставив во главу угла исходные тексты, вместе с крайней желательностью (а зачастую — и необходимостью) собирать их заново в каждой отдельной системе. Пока у C не было стандартов, исходники набивались #if'ами, учитывающими особенности отдельных реализаций компилятора/линкера. С появлением стандартов стало возможным избавиться от части условий, но тут (внезапно) выяснилось, что стандарты не одобряют хаков. А среди сишников-унихоидов как раз довольно много тех, у кого "это моя программа! это моя машина! не сметь диктовать мне, что я могу делать, а что нет!". Но они ж пишут не только для себя, однако привычки настолько укореняются, что контролировать их непросто.
A>они могут и для явно записанных пар сравнений сгенерировать функцию и её вызов.
Если это хотя бы не менее эффективно, чем последовательный код — почему нет? А если вдруг менее, то с какой стати оптимизатору намеренно ухудшать эффективность?
A>чтобы с этими волками жить, надо по-волчьи выть. А именно, писать тот код, который максимально чётко показывает, что ты хочешь.
Дык, волки тут ни при чем — к такому имеет смысл стремиться всегда и везде, независимо от. Чем более ясно выразишь свои идеи и намерения, тем выше вероятность, что тебя поймут правильно. Именно к этому я всегда и призываю в развитии любых ЯП. И для этого вовсе не обязательна "исходная" многословность, вроде паскалевских begin/end — запись может быть и лаконичной, лишь бы была возможность развернуть ее в удобночитаемую форму при нужде.
A>И если оптимизирующий компилятор сделал что-то, чего ты не хочешь, надо ругаться с автором компилятора. Так делает Линус, так делают разные программисты из статьи, на которую я дал ссылку.
Логично. Поэтому очень желательна возможность управления оптимизацией на "тонком" уровне, а не только через ключи компилятора.
A>А если ты явно описываешь функцию, пусть даже помеченную inline, то ругаться уже бесполезно. Тебя ткнут носом в стандарт, и спросят, на что ты жалуешься.
На этот случай в популярных реализациях есть атрибуты вроде __forceinline. По-хорошему, их лучше бы внести в стандарт, но "коллектив авторов", среди которых почти сплошь прикладники-абстракционисты, будет активно возражать.
A>Это уже спор о терминах. Я имел в виду именно это.
Препроцессор — он потому и "пре", что заканчивает свою работу еще до начала следующей стадии (анализа кода компилятором). Даже если он совмещен с компилятором, то должен работать на чисто текстовом уровне, сразу после выделения минимально возможных синтаксических конструкций. По-хорошему, приличный макропроцессор такого типа полезен в любом языке, и в C/C++ тоже не помешал бы, благо реализуется достаточно просто.
A>Кастинги мне нужны как в Си, точка. По очень многим причинам, я их не буду здесь перечислять.
А было бы интересно. У меня не самые примитивные программы, но от преобразований что в стиле C, что в "функциональном" плюсовом, я избавился достаточно давно, и никаких сколько-нибудь заметных напрягов это не потребовало.
A>Если "пометка в тексте программы" это X_cast<T>, то неважно, что об этом думаю я, это будет конец паразитированию на Си и, как я сильно подозреваю, конец мифу о популярности C++.
Еще интереснее. Что ж и Вы, и другие "паразиты", такого делаете, что переход на X_cast<> может заставить Вас отказаться от языка? У вас эти преобразования в каждой второй строке? Или хотя бы в каждой пятой?
A>>>Нахера мне нужен язык с ручным управлением памятью, если в нём кастинг и инициализация работают не как в Си? A>Какие ты привёл примеры ("столь же "молчаливая" обработка C-style cast, определение неинициализированных переменных без нужды и подобное"), на то я и ответил.
Увы, я по-прежнему не могу понять, о чем именно идет речь.
A>и Си уже не тот. Си теперь тоже дофига высокоуровневый.
В нем от "высокоуровневости" все больше синтаксического сахара. Да, позволяет более изящно записывать отдельные конструкции. Но при усложнении программы сложность кода растет все так же. Возможностей сколько-нибудь удобно комбинировать сущности между собой, как в C++, по-прежнему нет. И не будет, скорее всего.
A>>>Создатели плюсов поступили очень умно, решив, вот именно, ПАРАЗИТИРОВАТЬ на Си. Если бы они сделали всё то, что ты предлагаешь, у них бы получилось что-то типа D. То есть, дико популярное, но только в очень узких кругах.
ЕМ>>По-Вашему, большинство голосишников — маргиналы, стремящиеся уйти от любого контроля только потому, что это контроль, и он теоретически может ограничить их личную свободу?
A>или виртуальная машина (CLR, JVM, V8 и т.п.) и гарантия отсутствия проблем с памятью, или ответственность на мне, но я должен понимать, что происходит, и контролировать ситуацию.
Промежуточные варианты не рассматриваются? Например, возможность привязки к конкретным реализациям VM, или автоматизация управления памятью?
A>Если я объявил переменную, но не проинициализировал, значит под неё выделилась память, и она содержит всякую фигню. Всё, дальше я сам.
Почему не возникает резонного вопроса "как построить программу так, чтобы объявить переменную, но не инициализировать ее, было технически невозможно"? На худой конец — чтобы компилятор был обязан обнаруживать все подобные ситуации, и генерировать ошибку (а не предупреждение), если переменная в тексте явно не снабжена хорошо заметной пометкой типа "да, я нарочно объявил ее здесь, и буду за это отвечать". Тогда что компилятор, что внешний анализатор, могли бы для любой программы показать список таких пометок, чтоб при поиске причин глюков знать, куда смотреть в первую очередь.
A>Если я что-то делаю с указателем, то делаю что-то с указателем. Иначе возникает ситуация, когда компилятор меня ограничивает, но ни за что не отвечает.
Почему не отвечает? Целью любых стандартов, что в производстве, что в программировании, являются повышение надежности и предсказуемости — к сожалению, часто в ущерб экономичности. Не нужно бороться со стандартизацией, как явлением — нужно предусматривать возможность явно и хорошо заметно декларировать "я намеренно отступаю от стандарта". И тогда сразу видно, кого бить по наглой рыжей морде — компилятор, который соблюдает стандарт ценой снижения эффективности, или программиста, взявшего на себя больше, чем он смог вынести.
A>в полной мере применимо и к старому доброму Си, как его теперь видят зумеры. Это не эксклюзивно проблема С++.
Совершенно верно: зумеры хотят, чтоб все стало как можно проще, зубры хотят, чтоб все осталось, как раньше. Вместо того, чтобы искать разумный компромисс, обе стороны уперлись в "нет, должно быть только по-нашему, и никак иначе".
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Я бы сказал, что в вашем обсуждении народ просто развлекался для разминки мозгов. Одни это любят, другие не понимают. Я вот тоже считаю, что напрягаться для решения задачи имеет смысл, когда задача возникла более-менее естественным путем, а не когда ее создали искусственно. В жизни и так хватает задач, которые возникают сами собой, чтобы отвлекаться еще и на решение специально созданных — напоминает анекдот про гамак и лыжи.
Я же не виноват, что ты видел мало кода в своей жизни.
Эти сравнения сплошь и рядом встречаются, например, при поддержке железа. Вендор выпустил модельную линейку, в которой у каждой модели уникальный профиль поддержки багофич, ты в рантайме запросил ModelId и вперёд. Это пример из проекта, где is_in_set() встречался буквально десятками.
Збс, конечно. "Я не видел, значит это никому не надо".
ЕМ>Это Вы теорий заговора начитались. Медицина в эту сторону копает с 80-х — то есть, со времен, как только вирус был выделен. Но все прогнозы пока неутешительны. Даже с вирусом простого герпеса, который куда сильнее локализован, пока справиться не могут — слишком сложно.
Эта теория заговора называется "рыночная экономика". Фармкомпании вкладывают деньги в то, что принесёт деньги, быстро и много. Ты явно не читаешь обзоры этого бизнеса.
A>>каком виде надо записывать такие сравнения, чтобы эта ошибка стала невозможной?
ЕМ>"Ни в каком, бл#! Теперь — в твердом переплете".
Мне уже понадоела шымжа-стайл философия, если честно. Записав код как foo(v, 1, 2, 3), ты больше не сможешь пропустить v ==. Да, это всё, чего мы добились. Кофе такой код не варит, ото всех болезней не лечит, на бирже не торгует, в ж не целует. Он не нужен.
A>>Как выработать здоровую привычку для здорового кода? Такую, как Йода-сравнения, например.
ЕМ>В таких привычках нет ничего здорового. Это просто очередной кривой костыль, на безрыбье. С тех пор, как компиляторы начали выдавать предупреждения на потенциально опасное присваивание (где-то с 90-х, если не ошибаюсь), это задомнапередное сравнение полностью потеряло смысл.
Хорошо, когда ты все компиляторы повидал. А если чего-то и не видал, то в этом нет смысла.
А я вот ещё недавно собирал плюсовую программу под одну железяку очень специальным компилятором, который ворнингами не баловал. Не говоря уж о том, что если у тебя в одном проекте код на плюсах и каком-нибудь интерпретируемом DSL, тебе лучше выработать здоровую привычку всегда писать единообразно.
ЕМ>Как и многие другие, куда более актуальные. Хотя даже не сомневаюсь: если заинтересовать ею "шаблонных хакеров" во главе с Александреску, Степановым и иже с ними, через некоторое время они родят внешне приемлемое решение, но вот реализацию его будет лучше не смотреть на ночь.
Вот это точно.
A>>Оптимизаторы массово посходили с ума, и творят страшные вещи. Это касается теперь и Си, к сожалению.
ЕМ>Подобные тексты советую читать с изрядной долей скептицизма. Их авторы традиционно путают особенности реализаций, которые зачастую бывает удобно и полезно использовать именно для конкретных платформ, с условной "С-машиной", которую описывает стандарт. Они хотят странного — чтоб стандарт одновременно обеспечивал и неограниченную переносимость, и предельную эффективность любой конкретной реализации, и чтоб нигде не возникало UB. А это принципиально невозможно — либо абстракция, либо конкретика, третьего не дано.
А я советую прочитать примеры, которые они приводят. Переписки, в т.ч. Если раньше скандалов с хипстооптимизаторами не было, а сейчас они есть, значит что-то изменилось.
ЕМ>Логично. Поэтому очень желательна возможность управления оптимизацией на "тонком" уровне, а не только через ключи компилятора.
Такая возможность в данном случае называется "явный (не)вызов функции". Если ты в явном виде вставил вызов функции, ты больше не можешь жаловаться, что оптимизатор сгенерировал call.
ЕМ>На этот случай в популярных реализациях есть атрибуты вроде __forceinline. По-хорошему, их лучше бы внести в стандарт, но "коллектив авторов", среди которых почти сплошь прикладники-абстракционисты, будет активно возражать.
__forceinline нужен не для этого случая, лол. А для случая, обратного ему. Его, конечно, хорошо было бы стандартизировать. А кто тут абстракционист, советую перечитать свою философию про "только дурак будет пользоваться системой, защищающей от ошибок" в ответ на конкретный вопрос.
Здравствуйте, Alekzander, Вы писали:
A>Это пример из проекта, где is_in_set() встречался буквально десятками.
Я правильно понимаю, что Вы одобряете использование множественных сравнений "десятками", без стремления преобразовать их в более адекватный вид (switch, таблицу или битовые маски), и выступаете лишь за то, чтобы подобный кондовый код писали и дальше, лишь бы делали в нем меньше опечаток?
A>Эта теория заговора называется "рыночная экономика". Фармкомпании вкладывают деньги в то, что принесёт деньги, быстро и много.
Какие-то компании вкладывают деньги иначе?
А фармкомпании вкладываются в разработку АРТ прежде всего потому, что есть госзаказы на нее, объем которых значительно больше, чем совокупность индивидуальных. Они и стабильнее, и расценки там можно предложить выше. Так вот получилось, что препараты для достаточно эффективной АРТ удалось создать раньше, чем препараты для полного излечения. На этом безрыбье любому государству выгоднее сдерживать у себя эпидемию с помощью АРТ, чем ждать, пока сделают радикальную терапию.
Тем не менее, над радикальной терапией продолжают работать, и достаточно интенсивно. Просто потому, что АРТ ни разу не безвредная — она лишь заменяет относительно скорую и весьма неприятную смерть от СПИДа более длительной, но не слишком приятной жизнью на АРТ. Мало у кого получается сидеть на АРТ и продолжать безмятежно радоваться жизни.
A>Ты явно не читаешь обзоры этого бизнеса.
Я не читаю текстов, у которых явно прослеживается цель создания определенной точки зрения и/или позиции у читателя.
A>Записав код как foo(v, 1, 2, 3), ты больше не сможешь пропустить v ==.
Но по-прежнему смогу сделать десятки-сотни других ошибок, в том числе логических и неочевидных.
A>Да, это всё, чего мы добились.
Именно — изощренными приемами, к которым есть резонные вопросы (тот же возможный вызов) понизили вероятность отдельно взятой ошибки, при том, что эту самую вероятность никто не оценивал. То есть, внезапно обнаружили, что есть какой-то риск, и приняли активные меры для того, чтобы этого риска избежать. А о том, что рядом могут быть (и, скорее всего, есть) гораздо более высокие риски, предпочли не думать. Это распространенный подход — предотвращать не то, что наиболее вероятно, а то, что почему-то больше всего пугает.
A>А я вот ещё недавно собирал плюсовую программу под одну железяку очень специальным компилятором, который ворнингами не баловал.
Если Вы эту программу не писали специально под эту железку, и код более-менее переносимый, то его правильность можно проверять более умным компилятором. А если именно специально под нее, то сколько можно найти таких компиляторов? Ну не повезло конкретно Вам, зачем же отстаивать приемы, которые для большинства давно потеряли актуальность?
A>если у тебя в одном проекте код на плюсах и каком-нибудь интерпретируемом DSL, тебе лучше выработать здоровую привычку всегда писать единообразно.
Хм, и сколько таких DSL, где можно писать код "единообразно" с плюсовым, чтоб это не просто было в одном стиле, а действительно уберегало от ошибок?
A>А я советую прочитать примеры, которые они приводят.
Читал я подобные переписки. В одном, помнится, дошли аж до возмущения тем, что в цепочечном сравнении вроде Вашего оптимизатор вставил ветвление, которое "снижает быстродействие", а не преобразовал выражение так, чтобы обойтись арифметикой и логикой. И никто ведь не вспомнил, что компилятор, по-хорошему, вообще не имеет права вычислять правые выражения до того, как будут получены и проверены результаты левых.
Повторю: бороться нужно не с оптимизациями, как таковыми, а с их неочевидностью. То есть, настаивать на поддержке в языке (или хотя бы в компиляторах) средств, позволяющих избежать нежелательных оптимизаций. На худой конец — чтоб компилятор предупреждал, что конструкция кажется ему бессмысленной, и он как-то редуцирует.
ЕМ>>Логично. Поэтому очень желательна возможность управления оптимизацией на "тонком" уровне, а не только через ключи компилятора.
A>Если ты в явном виде вставил вызов функции, ты больше не можешь жаловаться, что оптимизатор сгенерировал call.
Если я вставил вызов функции с __forceinline — могу.
A>__forceinline нужен не для этого случая, лол. А для случая, обратного ему.
Я запутался в Вашей логике. Вы начали с опасения о том, что вызов функции не развернется в код в точке вызова, а будет сгенерирован call, и inline не гарантирует непосредственной вставки. Я предложил __forceinline, но "это снова не то". А что нужно-то?
Для "случая, обратного ему" VC++ есть __declspec(noinline). Вроде и у GCC тоже такое есть.
Здравствуйте, qqqqq, Вы писали:
Q>Так это не только совместимость C++ с С а и между разными компиляторами на С++ тоже, так называемый name mangling у каждого свой.
Я уже дважды повторял, что речь не об этом. С разморозкой!
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Если элементов (идентификаторов) не больше, чем количество разрядов в машинном слове, то сравнения вообще не нужны. Нужно преобразовать проверяемое значение в битовую маску, и с помощью команды типа test проверить, входит ли она в множество, образованное совокупностью представленных элементов. Множество (битовая маска) вычисляется на этапе компиляции. Если проверяемое значение заведомо не может быть вне множества, то не нужны даже предварительные сравнения на больше/меньше.
И при смене разрядности из-за смены платформы переписывать весь код? Спасибо, проходили, мне такое не надо.
Здравствуйте, Евгений Музыченко, Вы писали:
BFE>>И при смене разрядности из-за смены платформы переписывать весь код? ЕМ>Зачем весь?
Если автор привязывает код к архитектуре, то он редко делает это только в одном месте. Хотя, конечно, бывают исключения.
Здравствуйте, B0FEE664, Вы писали:
BFE>Если автор привязывает код к архитектуре, то он редко делает это только в одном месте. Хотя, конечно, бывают исключения.
Зависит от автора. Ну и битовые операции есть на любой архитектуре. Если софт писан во времена расцвета 32-разрядной, какова вероятность, что приспичить собирать под 16-разрядную?
BFE>К тому же не забываем про фатальный недостаток
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Тогда уж критикуйте и тех, кто предлагал switch.
switch невозможен для повторяющихся значений констант и для объектов.
Кстати, есть ещё вариант C++23:
constexpr auto arrErrs = std::array{EAGAIN, EWOULDBLOCK, EINTR, ENOSPC, ENOBUFS, ENOMEM};
if ( std::ranges::contains(arrErrs, errno) )
...
или
if (const auto arrErrs = {EAGAIN, EWOULDBLOCK, EINTR, ENOSPC, ENOBUFS, ENOMEM}; std::ranges::contains(arrErrs, errno) )
...
Впрочем я ещё не перешёл на C++20, так что возможны, наверно, ещё варианты...
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>В чем может быть ценность этой совместимости, кроме поощрения ленивых и малограмотных? Может, я чего не понимаю?
Я бы действовал наоборот, под лозунгом: "Пусть расцветают сто цветов!"
Ничего, кроме отсутствия ресурсов, не мешает добавить с С++:
extern"D"
{
// code на D
}
extern"Java"
{
// code на Java
}
extern"Rust"
{
// code на Rust
}
Перед использованием подобных конструкций я бы сперва посмотрел, в какой код они компилируются. Иначе легко можно нарваться на активное использование динамической памяти.