Здравствуйте, Евгений Музыченко, Вы писали:
R>>Сейчас вся эта кухня движется в сторону "чистых" структур без макросов с использованием компайл-тайм рефлексии.
ЕМ>Вот я и говорю, что она так "движется" уже десятки лет, и каждое незначительное, дозированное улучшение подается, как радикальный прорыв, от которого еще совсем немного до полного счастья. Кто-то искреннее радуется и гордиться, а мне кринжово.
Ну да, ну да. А если бы начиная с 1980-х вместо шаблонов начали пилить ваши гипотетические макросы, то все бы развивалось гораздо быстрее и мы имели бы Nemerle метапрограммирование на "мега-макросах" уже в C++98.
Именно так бы оно и было, вот-те-крест.
Re[39]: The Big OOPs: Anatomy of a Thirty-five-year Mistake
В этом подходе у тебя так или иначе присутствуют фрагменты кода, требующие ручной синхронизации. В моём подходе все происходит 100% автоматически. Для обширных форматов данных, которые к тому же сопровождаются несколькими людьми, это важно.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, so5team, Вы писали: S>Это у разработчиков на языках Visual C++ или Borland C++, коих в свое время было немало и которых вообще не интересовало, есть ли условный __property в языке C++ или нет.
Ну ок. #настоящийшотландец.
S>Ну и вы пытаетесь рассказывать байки человеку, который уже 30 лет компилирует программы посложнее хелловорлда разными компиляторами на разных платформах.
Угу. Угу. S>Вы хотите сказать, что у вас на ARM умножение float-ов будет работать не так, как на x86?
Естественно. А вы как думали, чудеса случатся? Даже на интеле результат умножения флоатов будет сильно зависеть от флагов компилятора (которые, естественно, никаким стандартом не регулируется) S>Т.е. если вы умножите 2.5 на 3, то в одном случае получите 12.75, а в другом 36.8?
Нет, не настолько. Но запросто настолько, что у вас ход исполнения программы пойдёт по другой ветке.
S>О том, что стадия препроцессинга почему-то выдается за проблему.
Ничего подобного. Это вы почему-то пихаете эту стадию как достоинство компилятора. В то время, как она, мягко говоря, сильно ограничена.
S>Сам по себе препроцессор a) безобиден и b) местами удобен. S>Проблемы, как водится, начинаются от людей, которые застряли в прошлом веке и, например, используют define вместо констант.
Отож. И ещё пятьсот способов неверно использовать препроцессор — во всём виноваты пользователи, а не экосистема.
В которой до сих пор нет твёрдого решения, что лучше использовать — import guards или #pragma once. Потому что оба сломаны
S>Тут бы еще понять что вы понимаете под базовыми возможностями языка. Т.к., например, объявление класса или функции вообще никак к текстовой склейке не относится.
Конечно не относится. И использование класса в другой единице трансляции по идее тоже не должно никак относиться к текстовой склейке, но увы — ничего другого С++ вплоть до совсем-совсем недавнего времени не предлагал. Вот это как раз самые что ни на есть базовые возможности языка — когда вам даже для hello world программы необходимо тащить текстовую склейку (которая к вашим 8 строкам кода любезно запрепендит ещё полмегабайта текста, чтобы компилятор не скучал), то это в 21 веке вызывает только недоумение.
S>Открыть вам страшную тайну? В С++ вы можете тоже самое.
Что "тоже самое"? Отказаться от препроцессора? Ну-ну. S>Более того, за счет препроцессора вы в одной единице трансляции можете подключить хоть 100500 разных мелких кусочков, сгенерированных внешними инструментами. Ну так он ни на что большее-то и не способен. Давайте, сделайте мне на препроцессоре разбор JSON-schema и генерацию кода сериализации/десериализации. Ах, для этого нужен целый отдельный инструмент?
После которого уже наконец можно будет запускать препроцессор? Ну, так если я уже взялся генерировать код руками — мне препроцессор, собственно, зачем? Вопрос риторический.
S>Речь не про ошибочность реализации. Речь о том, что решение добавить модули в язык с 35 летней историей и миллиардами имеющихся на руках строк кода -- это диверсия. Похлеще раскола на Python2 и Python3.
Ну, о том и речь — что неудачно принятое решение повлияло на всю историю, и труднообратимым образом.
S>Речь шла именно о том, что в далекие годы, когда у кого-то в распоряжении был только С-шный компилятор, а у кого-то уже и C++ный, библиотеки писались так, чтобы их можно было компилировать либо С-шным компилятором, либо C++ным, в зависимости от того, что есть под рукой. S>Условно: S>
S>// Заголовочный файл my_lib.h
S>#ifndef MY_LIB_H
S>#define MY_LIB_H
S>#ifdef __cplusplus
S>#define DEFAULT_ARG_VALUE(v) =v
S>#endif
S>void do_something(int a, int b DEFAULT_ARG_VALUE(0), int c DEFAULT_ARG_VALUE(1));
S>...
S>
Спасибо за пояснение. По-прежнему решительно непонятно, что тут может помешать использовать модули. Собрал С-шным компилятором — получилась С-шная библиотека. Собрал С++ным — получился С++-ный модуль. А если чутка по-другому сделать, то получится С++-ный модуль, оборачивающий С-шную библиотеку.
S>Отголоски этого и сейчас можно видеть. Например, в некоторых C++ных библиотеках, которые активно применяются в разных языках, можно увидеть типичную конструкцию с extern "C".
Ну в данном конкретном случае это С-шная библиотека. И, естественно, extern "C" нужен как раз для плюсовых клиентов библиотеки, чтобы плюсовый компилятор использовал корректные имена символов при импорте.
И это никакие не отголоски, а суровая необходимость, при использовании библиотеки через границу языков.
S>Пжалста, не нужно в очередной раз демонстрировать дурость типичных евагнелистов -- врываться в темы, не относящиеся к вашей любимой игрушке и рассказывать о ее достоинствах, о которых вас никто и не спрашивал.
Во-первых, речь про дотнет завели вы, а не я. Не хотите слушать про дотнет — не огрызайтесь на него там, где не просят.
Во-вторых, тема как раз относится к моей "любимой игрушке". Просто вы не знаете, какая игрушка у меня любимая, отсюда ваша фрустрация.
S>>Обе принятые в плюсах методики метапрограммирования выглядят неудачными
S>Нуждается в доказательствах. Причем не в сравнении с какими другими языками (это сравнение не имеет смысла когда разработка ведется на C++), а применительно конкретно к C++.
Ну прямо доказать тут не получится — потому что то, что одному кажется ужас-ужасом, другому кажется норм.
Но в целом ситуация примерно такая: макросы препроцессора совсем ничего не знают о контексте, кроме переданных им текстов, и на них невозможно организовать совсем никакие вычисления, кроме опять же склейки переданных им текстов.
Шаблоны как раз что-то "знают" о контексте: им можно передавать типы, и шаблоны умеют выполнять какие-никакие трансформации с этими типами.
Но выполняемые трансформации ограничены, фактически, прямой подстановкой; единственной конструкцией для обработки структур является рекурсия, а единственной конструкцией для выбора альтернатив является SFINAE и частичная специализация, чтобы заставить ненужные подстановки сфейлиться.
Какие могут быть варианты? Без слома совместимости — только метапрограммирование на AST. Вот по соседству советуют CastXML — как раз инструмент для тех, кому не хочется продираться сквозь "а вот есть ешё такой приём", чтобы решить какую-нибудь прикладную задачу по конструированию типа T1 по типу T2, или там функции F по типу T, или там типа T по сигнатуре функции F.
Со сломом совместимости можно было бы попытаться заменить алгебру типов, позволяя всякие конструкции типа type P<T> = T extends Q ? T : Q. Возможности будут примерно те же, только написанные "прямым" способом, а не шиворот-навыворот.
S>Кто считает? Я считаю? S>Помилуйте, я всего лишь сказал, что перцы из HFT/HPC нуждаются в продвинутых возможностях шаблонов и привел CRTP как пример. Поскольку в качестве замены виртуальных вызовов CRTP действительно может давать прирост производительности.
Ну, насколько я знаю, перцы из HFT/HPC даже джавой не брезгуют, что делает ваше предположение о необходимости CRTP для них не шибко убедительным.
S>Если для вас это пример "низкоуровневой оптимизации", то мне здесь даже и добавить нечего.
А то. Всякий раз, как вы начинаете считать такты на косвенный вызов и байты на VMT — это низкий уровень. Высокоуровневые оптимизации — это те, которые на асимптотику влияют. Типа замены N^2 на NlogN. А когда вы боретесь за коэффициент при N — низкий уровень, увы.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Во-первых, речь про дотнет завели вы, а не я. Не хотите слушать про дотнет — не огрызайтесь на него там, где не просят.
Я про .NET вообще речь не заводил. Я вас назвал .NET пропагандоном, поскольку вы относитесь к той токсичной категории .NET-проповедников, которые за пределами завязанных на .NET-разделов характеризуются:
Собственно, все эти качества вы здесь в полной мере и проявили. При этом еще и многократно приписав мне то, чего я вообще и не говорил, и не подразумевал.
Посему остается только сказать -- шли бы вы и занимались бы .NET-евангелизмом где-то где вам будут рады.
Re[39]: The Big OOPs: Anatomy of a Thirty-five-year Mistake
Здравствуйте, Marty, Вы писали:
M>Если бы ты сделалпридумал красивый (в архитектурном плане) и элегантно дополняющий плюсики язык "макросов", то вполне возможно, что его кто-нибудь бы и запилил, на том же Clang'e, и пропоузал бы закинул в комитет.
Я ж говорил, что подумывал это сделать. Но каждый раз, когда я об этом вспоминал, я видел, как в среде разработчиков языка безраздельно господствует подход "Мы научились многое делать на шаблонных трюках, и это хорошо, поскольку круто и необычно, а кому не нравится — тот ретроград и неосилятор. Так что нечего засорять язык и усложнять компилятор".
Если б в языке происходили хотя бы небольшие подвижки в этом направлении, я бы сподобился, наверное.
Тот же MS еще в начале 2000-х добавил в свой компилятор предикаты __is_xxx/__has_xxx, но сам же их почти не использовал.
Поэтому и говорю: это коллективное, массовое помешательство. Противостоять такому крайне трудно, у меня никогда не было нужных ресурсов для этого.
Re[40]: The Big OOPs: Anatomy of a Thirty-five-year Mistake
Здравствуйте, Евгений Музыченко, Вы писали:
M>>Если бы ты сделалпридумал красивый (в архитектурном плане) и элегантно дополняющий плюсики язык "макросов", то вполне возможно, что его кто-нибудь бы и запилил, на том же Clang'e, и пропоузал бы закинул в комитет.
ЕМ>Я ж говорил, что подумывал это сделать. Но каждый раз, когда я об этом вспоминал,
Когда я хочу что-то сделать — я сажусь и делаю
ЕМ>я видел, как в среде разработчиков языка безраздельно господствует подход "Мы научились многое делать на шаблонных трюках, и это хорошо, поскольку круто и необычно, а кому не нравится — тот ретроград и неосилятор. Так что нечего засорять язык и усложнять компилятор".
Нет, подход не такой. Использование SFINAE — вполне стало стандартным механизмом, и перестало быть крутым и необычным. И да, кто не осилил — тот неосилятор.
ЕМ>Если б в языке происходили хотя бы небольшие подвижки в этом направлении, я бы сподобился, наверное.
Все сидели и так и думали. И подвижек не происходило.
ЕМ>Тот же MS еще в начале 2000-х добавил в свой компилятор предикаты __is_xxx/__has_xxx, но сам же их почти не использовал.
Никогда не слышал о таком. __property (или уж __declspec(property)) для совместимости с IDL/COM видел, никаких __is_xxx/__has_xxx не видел. property — использовались, были нужны, а __is_xxx/__has_xxx видимо, не особо были нужны. Что они хоть делали?
ЕМ>Поэтому и говорю: это коллективное, массовое помешательство. Противостоять такому крайне трудно, у меня никогда не было нужных ресурсов для этого.
Нет, это у тебя персональное неосиляторство, о котором ты очень любишь поговорить.
Здравствуйте, Marty, Вы писали:
M>Когда я хочу что-то сделать — я сажусь и делаю
Ага-ага, а "если чего не сделал — того не хотел".
M>Использование SFINAE — вполне стало стандартным механизмом
Вот мне от этого и крижово. Реально стыдно за людей, по вине которых этот убогий механизм вышел за пределы забавного глюка для развлечения.
M>Все сидели и так и думали. И подвижек не происходило.
Я Вас умоляю. Если б хоть четверть ЛПРов действительно думала в этом направлении, а не предлагала одно за другим решения одно корявее другого, мы б давно увидели подвижки.
M>никаких __is_xxx/__has_xxx не видел. property — использовались, были нужны, а __is_xxx/__has_xxx видимо, не особо были нужны.
Ну дык, ежели "все знают", что предикат "выражение является классом" — это шаблон is_class <>, реализованный с помощью трюков, то "родной" предикат __is_class (), реализованный непосредственно в компиляторе, уже "не особо и нужен".
Re[42]: The Big OOPs: Anatomy of a Thirty-five-year Mistake
Здравствуйте, Евгений Музыченко, Вы писали:
M>>Использование SFINAE — вполне стало стандартным механизмом
ЕМ>Вот мне от этого и крижово. Реально стыдно за людей, по вине которых этот убогий механизм вышел за пределы забавного глюка для развлечения.
Этот "забавный глюк" показал востребованное направление развития языка и трансформировался в концепты и констрейнты. И те, кто хотя бы понимал возможности, предоставляемые SFINAE, с радостью перешёл на новые возможности языка.
Ну а ты не только никогда не умел пользоваться SFINAE, ты даже не понимаешь, зачем он нужен и какие задачи позволяет решать. Соответственно и к концептам у тебя такое же отношение. Всё, что находится за пределами твоего понимания — это "трюки" "глюки" и "магия". И проклятые комитетчики, которые вечно мешают тебе танцевать.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, Евгений Музыченко, Вы писали: M>>Когда я хочу что-то сделать — я сажусь и делаю ЕМ>Ага-ага, а "если чего не сделал — того не хотел".
Или не очень хотел. Но ты не первый десяток лет этого хочешь, можно было попытаться. Александреску вон, целый отдельный язык запилил уже
M>>Использование SFINAE — вполне стало стандартным механизмом ЕМ>Вот мне от этого и крижово. Реально стыдно за людей, по вине которых этот убогий механизм вышел за пределы забавного глюка для развлечения.
Этот "убогий механизм" просто работал, и его просто стали использовать. Не было каких-то людей, которые сказали, что нам нахрен не нужен офигенский механизм Музыченко, мы лучше будём пёхаться с SFINAE.
C++ вообще больше 10ти лет стагнировал, с 98го. 0x03 был просто причесанным 98ым, ничего принципиального не привнёс. И вот тогда и надо было выступать со своими идеями, может, к 11ому стандарту кто-то бы и проникся твоими идеями. Но тебе даже теоретически этот вопрос проработать было недосуг.
А потом, начиная с 11го стандарта, эти механизмы начали упрощать понемногу, пользуясь наработанными практиками. Тут надо понимать, что это всё — навесное, оно практически не затрагивает ядро языка, поэтому этим можно пользоваться и развивать любому.
Твои же предложения сильно бы затронули ядро языка, и хз, что бы там начало ломаться от этого
M>>Все сидели и так и думали. И подвижек не происходило. ЕМ>Я Вас умоляю. Если б хоть четверть ЛПРов действительно думала в этом направлении, а не предлагала одно за другим решения одно корявее другого, мы б давно увидели подвижки.
Не надо меня умолять.
Все решения — эволюционные, они минимально затрагивают уже существующее, и то каждый пропозал обсасывают со всех сторон.
Александресу это не понравилось, он свой язык запилил. Кстати, переходил бы на D, там наверняка есть то, что тебе нужно
M>>никаких __is_xxx/__has_xxx не видел. property — использовались, были нужны, а __is_xxx/__has_xxx видимо, не особо были нужны. ЕМ>Ну дык, ежели "все знают", что предикат "выражение является классом" — это шаблон is_class <>, реализованный с помощью трюков, то "родной" предикат __is_class (), реализованный непосредственно в компиляторе, уже "не особо и нужен".
Ну вообще-то, ты не поверишь, но в том же GCC есть реализованные непосредственно в компиляторе __is_enum, __is_union, __is_class, и std::is_XXX реализованы именно через них, без всяких "трюков".
Возможно, изначальные реализации в каком-то бусте или у Александреску и были реализованы на "трюках", народ стал использовать; в итоге, как полезняху, добавили в стандарт, компиляторостроители решили, что сделать builtins для этого упростит реализацию этих шаблонов и ускорит компиляцию, и будет стоить им малой крови, и просто взяли и добавили это в свой компилятор в том или ином виде.
Фишка в том, что это низкоуровневые детали реализации, и компиляторостроитель может этот уровень реализовывать так, как ему удобнее. Стандарт же C++ тебе гарантирует наличие std::is_XXX, а как оно унутре библиотеки конкретного компилятора реализовано — стандарту пофик. Пусть хоть и нет встроенной поддержки, а реализовано "трюками", стандарту пофиг.
Если ты заглянешь в MSVC-шный <type_traits>, то там ты обнаружишь аналогичную GCC-шной реализацию std::is_class сотоварищи.
Теперь тебе понятно, почему MS не использует свои __is_enum, __is_union, __is_class? Они их использовали ровно в одном месте, там, где без этого было не обойтись, а дальше они пишут на стандартном C++ и используют std::is_enum, std::is_union, std::is_class...
По факту, ты третий десяток лет регулярно находишь время поныть, как всё в C++ плохо, через жопу с трюками, но не нашел и получаса, чтобы посмотреть, как на самом деле устроен анноящий тебя std::is_class
Здравствуйте, Marty, Вы писали:
M>Александресу это не понравилось, он свой язык запилил. Кстати, переходил бы на D, там наверняка есть то, что тебе нужно
Справедливости ради, не Александреску запилил D. Он подключился к D, когда тот уже был на пороге релиза версии 1.000.
И, как по мне, именно Александреску окончательно убил перспективы D набрать хоть какую-то значимую популярность, потому что вскорее после прихода Александреску было объявлено о планах D2, который, внезапно, не будет полностью совместим с D1. А потом еще и D2 превратился в долгострой, который очень много менялся прежде чем хоть как-то стабилизироваться.
г.Музыченко D вряд ли подойдет: там без GC в режиме betterC вроде как куча плюшек не работает, да и в режиме betterC для ядра Windows вряд ли драйвера попишешь.
Re[40]: The Big OOPs: Anatomy of a Thirty-five-year Mistake
Здравствуйте, Евгений Музыченко, Вы писали:
M>>Если бы ты сделалпридумал красивый (в архитектурном плане) и элегантно дополняющий плюсики язык "макросов", то вполне возможно, что его кто-нибудь бы и запилил, на том же Clang'e, и пропоузал бы закинул в комитет.
ЕМ>Я ж говорил, что подумывал это сделать. Но каждый раз, когда я об этом вспоминал, я видел, как в среде разработчиков языка безраздельно господствует подход "Мы научились многое делать на шаблонных трюках, и это хорошо
Евгений, а что языки программирования развиваются как-то иначе?
Обычная эволюция: сделали фичу X в том объеме и в том понимании, которое было на тот момент. Потом увидели как используется фича X, что хорошо, что нет. И если фича X востребована, то ее прокачивают дальше.
Как раз на примере шаблонов это прекрасно видно: сперва сделали шаблоны именно как инструмент для обобщенного программирования. Чтобы можно было написать std::vector и std::accumulate, не более того. Но за счет не побоюсь этого слова гениальности разработчиков (а к тому времени не только Страуструп занимался развитием языка) получилось настолько круто, что народ начал эксплуатировать "побочные эффекты" шаблонов. И когда это увидели, то неизбежно стали развивать это направление: в C++11 добавили variadic templates и стандартные type_traits, в С++17 -- fold expressions и if constexpr, в C++20 -- концепты. В итоге в C++26 добавили и метапрограммирование.
Что примечательно, метапрограммирование в C++26 позволит делать многое, но далеко не все, что сейчас можно сделать на С-шных макросах. И, возможно, еще через пару стандартов закроют и недостающие части.
ЕМ>поскольку круто и необычно
Но ведь это было реально круто и необычно.
Многие вещи, описанные Александреску, реально срывали покровы и открывали новый взгляд на то, как можно решать проблемы в C++. Мне вот сходу из таких policy based design вспомнинается. Хотя, наверное, и typelist-ы туда же.
ЕМ>а кому не нравится — тот ретроград и неосилятор. Так что нечего засорять язык и усложнять компилятор".
Ну вот я в 2000-х был таким ретроградом и неосилятором и много ругался на вещи вроде Boost.Lambda или чрезмерным увлечением вычислениями в compile-time на шаблонах. Потому что считал, что язык в его тогдашнем виде для таких наворотов не очень подходит, что лучше обходиться более традиционными и консервативными подходами, что нужно подождать пока в язык завезут нормальные средства.
И знаете что? Эти средства таки завезли. Как раз потому, что более смелые и прогрессивные разработчики эти фичи пусть даже и в эрзац виде стали широко использовать, с этим пришлось считаться и людям из комитета.
А если бы не застой в развитии C++ (о котором вам Marty уже сказал), все эти средства должны были появится в C++ гораздо раньше.
Но тут уж историю не переписать.
Re[41]: The Big OOPs: Anatomy of a Thirty-five-year Mistake
Здравствуйте, so5team, Вы писали:
S>языки программирования развиваются как-то иначе?
Я не слышал о других языках, где весьма обширный инструментарий десятки лет делался бы по принципу "потому, что это технически возможно", и этот процесс принял бы массовый характер. Вы слышали о таких?
https://www.youtube.com/watch?v=yyTPt0sus-g&t=108
S>за счет не побоюсь этого слова гениальности разработчиков (а к тому времени не только Страуструп занимался развитием языка) получилось настолько круто, что народ начал эксплуатировать "побочные эффекты" шаблонов.
Не было там гениальности. Как уже много раз подчеркивалось, возможность городить такие трюки была не создана, а открыта. Потом реализацию шаблонов лишь немного допилили в этом направлении, ну и зафиксировали на пару десятков лет.
S>И когда это увидели, то неизбежно стали развивать это направление: в C++11 добавили variadic templates и стандартные type_traits, в С++17 -- fold expressions и if constexpr, в C++20 -- концепты. В итоге в C++26 добавили и метапрограммирование.
Если б у них было желание "неизбежно развивать", то еще в начале 2000-х напрашивался ряд куда более продвинутых решений, чем эти скупые, дозированные, сугубо частные доработки. Ничем иным, как массовым помрачением, я это объяснить не могу.
S>Что примечательно, метапрограммирование в C++26 позволит делать многое, но далеко не все, что сейчас можно сделать на С-шных макросах. И, возможно, еще через пару стандартов закроют и недостающие части.
Остается вопрос — почему их не начали закрывать с этой стороны еще хотя бы двадцать лет назад? На мой взгляд, ситуация была предельно ясна даже на первый взгляд:
— Компилятор в ходе анализа программы собирает множество различных сведений.
— Компилятор мог бы отдавать эти сведения непосредственно через какие-нибудь служебные конструкции, но язык упорно избегает их вводить.
— В сложившейся ситуации изобретаются различные трюковые механизмы, косвенными методами добывающие у компилятора эти сведения, причем далеко не все. Но это объявляется годной, достойной практикой, и начинает всячески развиваться.
— Одновременно изобретаются трюковые механизмы обобщенного программирования, позволяющие порождать код условно и циклически, но никакой поддержки со стороны языка долгое время даже не планируется, а затем в этом направлении начинается очень медленное, крайне неохотное движение.
Опять же, с самого начала даже интуитивно понятно, что для устранения фундаментальных недостатков языка нужно вводить в него средства как извлечения сведений из компилятора, так и условного/циклического порождения кода. В том или ином виде такие средства были известны за десятки лет до этого. Вы знаете хоть сколько-нибудь серьезные и вдумчивые обсуждения на тему "что нужно добавить в язык, чтобы избавиться от необходимости использовать трюки, получить непосредственно от компилятора больше сведений за меньшую цену, и указывать непосредственно компилятору, когда порождать тот или иной код, а когда нет"?
S>Но ведь это было реально круто и необычно. S>Многие вещи, описанные Александреску, реально срывали покровы и открывали новый взгляд на то, как можно решать проблемы в C++.
Угу, какая-нибудь самомодификация кода, чтобы сделать косвенную адресацию, когда-то тоже была "крутой и необычной". Слава богу, хватило ума ввести косвенную адресацию и регистры в архитектуру, и не тащить уродство десятки лет под лозунгом "кому не нравится, тот ниасилятор". А ведь тогда приходилось все изобретать с нуля, даже идеи подсмотреть было негде.
S>я в 2000-х был таким ретроградом и неосилятором и много ругался на вещи вроде Boost.Lambda или чрезмерным увлечением вычислениями в compile-time на шаблонах.
Сама по себе идея вычислений в compile-time как раз прекрасна, и так или иначе была реализована в ряде языков задолго до C++. Нужно было всего-то признать, что эта вакханалия в первую очередь чешет ЧСВ Александреску со товарищи, и лишь в последнюю — дает пользователям адекватные, удобные и надежные средства решения практических задач. Но возражения были сугубо отдельными, достаточно робкими, отчего тонули в массовом увлечении модным/молодежным.
S>Эти средства таки завезли. Как раз потому, что более смелые и прогрессивные разработчики эти фичи пусть даже и в эрзац виде стали широко использовать, с этим пришлось считаться и людям из комитета.
Угу, когда тормозить и тянуть дальше стало уже совсем невмоготу, они начали завозить по паре капель, а Вам, на безрыбье, уже и это за счастье.
S>А если бы не застой в развитии C++ (о котором вам Marty уже сказал), все эти средства должны были появится в C++ гораздо раньше.
Я уже много раз подчеркивал, что дело не в застое. Дело в очевидно нездоровом подходе "ну как-то ведь получилось, пусть теперь так и будет, нечего от добра добра искать". Любой инженер Вам скажет, что это колхозный, обывательский подход. Ребята-новаторы с очумелыми ручками могут придумывать 100500 способов использования скотча и суперклея для сборки и ремонта водопровода, и даже устраивать всемирные конкурсы по этому делу, но в мало-мальски серьезном производстве так нельзя, фу так делать.
Re[42]: The Big OOPs: Anatomy of a Thirty-five-year Mistake
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Я не слышал о других языках, где весьма обширный инструментарий десятки лет делался бы по принципу "потому, что это технически возможно", и этот процесс принял бы массовый характер. Вы слышали о таких?
D, как минимум.
Кроме того, языков с настолько массовым использованием и развиваемых настолько большим комитетом, да еще и с результатом в виде ISO-стандарта, как я понимаю, больше нет. Из языков со стандартом вспоминается только Си. Но он по возможностям сильно меньше C++, да и то туда _Generic-и засунули.
Есть еще Ada, но она где-то на самом краю мейнстрима.
Вроде бы Java сейчас эволюционирует посредством предложений. Но там нет международного стандарта, одна компания сама выбирает на что именно обратить внимание. Не говоря уже про C#.
ЕМ>Не было там гениальности.
Мне как-то пофиг на вашу оценку.
ЕМ>Как уже много раз подчеркивалось, возможность городить такие трюки была не создана, а открыта.
Открыть ее смогли именно потому, что задел был гораздо больший чем это было нужно для условного std::accumulate.
ЕМ>Потом реализацию шаблонов лишь немного допилили в этом направлении, ну и зафиксировали на пару десятков лет.
Нет никаких десятков лет, хватит уже расписываться в своей безграмотности. Был большой разрыв между C++98 и C++11, который завершился тем, что C++ стал чуть ли не другим языком по своим возможностям. А после C++11 развитие C++, в том числе и его шаблонов, идет постоянно и поступательно.
S>>И когда это увидели, то неизбежно стали развивать это направление: в C++11 добавили variadic templates и стандартные type_traits, в С++17 -- fold expressions и if constexpr, в C++20 -- концепты. В итоге в C++26 добавили и метапрограммирование.
ЕМ>Если б у них было желание "неизбежно развивать", то еще в начале 2000-х напрашивался ряд куда более продвинутых решений, чем эти скупые, дозированные, сугубо частные доработки.
Какие? Блин, Евгений, дайте уже этот перечень.
Пока что у всех общающихся с вами складывается ощущение, что вы говорите исключительно о своих собственных идеях, которые никогда не увидили свет в формалированном и донесенном до общественности виде.
ЕМ>Ничем иным, как массовым помрачением, я это объяснить не могу.
Не можете из-за своего скудоумия и ограниченного кругозора.
S>>Что примечательно, метапрограммирование в C++26 позволит делать многое, но далеко не все, что сейчас можно сделать на С-шных макросах. И, возможно, еще через пару стандартов закроют и недостающие части.
ЕМ>Остается вопрос — почему их не начали закрывать с этой стороны еще хотя бы двадцать лет назад?
20 лет назад лично я вообще не верил в том, что C++ сможет прожить еще столько.
Тогда был такой сильный пресс со стороны безопасных языков, плюс фактический закат разработки под десктоп (сейчас в этой нише только жалкое подобие былой роскоши), плюс перла разработка под Web, плюс уже были зачатки будущего бума разработка под мобилки.
Т.е. было очевидно, что на С++ написано уже столько, что просто так он не исчезнет. Но была реальная опасность, что C++ превратиться в своего рода COBOL, только в другой нише.
ЕМ>- Компилятор в ходе анализа программы собирает множество различных сведений.
Эти сведения использовались компилятором для обслуживания шаблонов. Т.ч. эту вашу "возможность" уже эксплуатировали.
ЕМ>- Компилятор мог бы отдавать эти сведения непосредственно через какие-нибудь служебные конструкции, но язык упорно избегает их вводить.
В C++11 часть этих сведений отдаются через стандартные шаблоны, описанные в type_traits. Т.ч. эту вашу "возможность" уже реализовали.
ЕМ>- В сложившейся ситуации изобретаются различные трюковые механизмы, косвенными методами добывающие у компилятора эти сведения
Это не трюковые механизмы, а штатные механизмы шаблонов.
Никакой косвенности нет, все предельно понятно и в рамках все тех же штатных механизмов шаблонов.
ЕМ>- Одновременно изобретаются трюковые механизмы обобщенного программирования, позволяющие порождать код условно и циклически
Что за "трюковые механизмы"?
ЕМ>но никакой поддержки со стороны языка долгое время даже не планируется, а затем в этом направлении начинается очень медленное, крайне неохотное движение.
В C++ в очень многих местах крайне медленное движение. Поинтересуйтесь на досуге как долго в стандарт шли концепты из C++20 или ranges из C++20.
Или как долго идут executor-ы.
Очевидно, что когда язык разрабатывается комитетом, то быстрое развитие чего-то важного маловероятно.
ЕМ>Вы знаете хоть сколько-нибудь серьезные и вдумчивые обсуждения на тему "что нужно добавить в язык, чтобы избавиться от необходимости использовать трюки, получить непосредственно от компилятора больше сведений за меньшую цену, и указывать непосредственно компилятору, когда порождать тот или иной код, а когда нет"?
Достаточно поискать в интернете обсуждения первых предложений по метапрограммированию (которые, емнип, предлагали template-based подход). И обсуждения того, что сейчас включили в C++26 (value-based подход).
S>>Но ведь это было реально круто и необычно. S>>Многие вещи, описанные Александреску, реально срывали покровы и открывали новый взгляд на то, как можно решать проблемы в C++.
ЕМ>Угу, какая-нибудь самомодификация кода, чтобы сделать косвенную адресацию, когда-то тоже была "крутой и необычной". Слава богу, хватило ума ввести косвенную адресацию и регистры в архитектуру, и не тащить уродство десятки лет под лозунгом "кому не нравится, тот ниасилятор".
Я не понял этой аналогии.
ЕМ>А ведь тогда приходилось все изобретать с нуля, даже идеи подсмотреть было негде.
Да, те шаблоны, которые были реализованны в C++98 подсмотреть было негде. Ну вот вообще.
Обобщенное программирование в той же Ada сильно отличалось от такового в C++.
В ML, на который ссылался Страуструп, если не ошибаюсь, тоже.
S>>я в 2000-х был таким ретроградом и неосилятором и много ругался на вещи вроде Boost.Lambda или чрезмерным увлечением вычислениями в compile-time на шаблонах.
ЕМ>Сама по себе идея вычислений в compile-time как раз прекрасна, и так или иначе была реализована в ряде языков задолго до C++.
То, что реализовано где-то, как правило, совершенно бесполезно в C++ просто потому, что этого в С++ нет.
Вот абсолютно бесполезно знание того, как работает GC в Java. Или как в Java сделаны аннотации.
Или как в D работает mixin templates.
Информация об этом может быть полезна тем, кто хочет внедрить что-то в C++. Но чтобы внедрить нужно сперва придумать, как это вообще в С++ сделать.
На примере с паттерн-матчингом можно увидеть, что "придумать" далеко не просто.
ЕМ>Но возражения были сугубо отдельными, достаточно робкими, отчего тонули в массовом увлечении модным/молодежным.
У меня нет ощущения, что увлечение было настолько массовым и модным, как вы здесь расписываете. Потому что
a) чем больше сложных шаблонов использовалось в коде, тем медленнее все компилировалось и тем чаще компиляторы падали в ICE;
b) чем больше сложных шаблонов использовалось, тем меньше членов команды могло адекватно работать с кодом.
Так что, как видилось это с моей колокольни, было много разговоров на форумах (в том числе и здесь, на RSDN), но гораздо меньше это встречалось в реальных кодовых базах.
ЕМ>Угу, когда тормозить и тянуть дальше стало уже совсем невмоготу, они начали завозить по паре капель, а Вам, на безрыбье, уже и это за счастье.
Когда очередная версия стандарта позволяет мне делать меньше приседаний, то это, конечно же, радует.
А вот вы, вероятно, просто всю жизнь занимаетесь совершенно тупой и однообразной работой по перекладыванию битиков в байтиках. И для вас нужен просто более безопасный Си с более продвинутыми макросами. Но т.к. такого нет, то вы и вынуждены жить в Си-с-классами.
S>>А если бы не застой в развитии C++ (о котором вам Marty уже сказал), все эти средства должны были появится в C++ гораздо раньше.
ЕМ>Я уже много раз подчеркивал, что дело не в застое. Дело в
вашем скудоумии.
Re[8]: The Big OOPs: Anatomy of a Thirty-five-year Mistake
Здравствуйте, ·, Вы писали:
S>>И вот тут и возникает некоторая проблема — как запретить порождать других наследников от Expression? В каком-нибудь дотнете это достигается package visibility для Expression. ·>А как package visibility позволит сделать exhaustiveness checking?
public class Expression {
internal Expression() {}
}
объявить наследника Expression в другой сборке конечно можно. Но так как создать экземпляр этого наследника всё равно нельзя будет создать, то и в pattern matching таких наследников можно не учитывать.
Re[9]: The Big OOPs: Anatomy of a Thirty-five-year Mistake
Здравствуйте, Jack128, Вы писали:
J>·>А как package visibility позволит сделать exhaustiveness checking? J>
J>public class Expression {
J> internal Expression() {}
J>}
J>
J>объявить наследника Expression в другой сборке конечно можно. Но так как создать экземпляр этого наследника всё равно нельзя будет создать, то и в pattern matching таких наследников можно не учитывать.
В тех же плюсах такую же хрень можно через private+friend сделать.
В java — через приватный конструктор или интерфейс и inner-классы в качестве наследников. Здесь один недостаток(?), код всех таких классов должен лежать в одном .java-файле.
Правда, причём тут exhaustiveness checking?!.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Евгений Музыченко, Вы писали:
S>>Со времен C++98. Здесь можете посмотреть раздел 3.10.15.
ЕМ>Во-первых, там речь об lvalue, а для того, о чем писал я, достаточно rvalue.
Так rvalue указателей в C++ не завезли пока. Как только ты попробуешь доступиться к данным через эти указатели, ты получишь lvalue и тот самый UB. Тебе зачем указатели, которые нельзя разыменовывать?
ЕМ>Во-вторых, не вижу там характерных слов, вроде "impossible", "unsupported", "not implemented" и подобных. Возможно, недостаточно знаю английский.
А слова "behavior is undefined" видишь? В переводе на русский это означает "поведение не определено". В переводе на ещё более русский — ХЗ, чё будет делать твоя программа при следующем запуске.
--
Справедливость выше закона. А человечность выше справедливости.
ЕМ>Остается вопрос — почему их не начали закрывать с этой стороны еще хотя бы двадцать лет назад? На мой взгляд, ситуация была предельно ясна даже на первый взгляд:
Дипсик говорит:
Утверждение о "большом перерыве" верно лишь отчасти. Правильнее сказать, что был один очень долгий и продуктивный перерыв между двумя ключевыми стандартами: C++98 и C++11, который длился 13 лет. После этого развитие пошло быстрыми темпами.
Давайте разберемся, почему так произошло.
После выхода стандарта C++98 сообщество и комитет по стандартизации поняли, что для решения современных задач (многопоточность, более сложные абстракции) язык нуждается не в косметических улучшениях, а в глубокой эволюции.
Вот ключевые факторы, которые обусловили эту паузу:
1. Сложность и масштабность новых features
Комитет (ISO/IEC JTC1/SC22/WG21) работал над вещами, которые меняли сам дух языка. Это были не просто новые библиотеки или ключевые слова, а фундаментальные механизмы:
Шаблоны (Templates): Разработка "шаблонов с переменным числом аргументов" (variadic templates), которые легли в основу современных библиотек.
Move-семантика и rvalue-ссылки (&&): Это была революция для производительности, позволяющая избегать лишних копирований объектов. Ее концепция и реализация были крайне сложными.
Концепция "Concepts": Попытка кардинально улучшить систему шаблонов, сделать ошибки компиляции читаемыми. Эта работа заняла много лет и в итоге не успела в C++11, войдя лишь в C++20.
Модель памяти (Memory Model): Для поддержки многопоточности "из коробки" нужно было определить формальную модель памяти, которая гарантировала бы корректное поведение в многопоточной среде. Это геркулесов труд.
2. Процесс стандартизации: Консенсус и обратная совместимость
Консенсус: Комитет состоит из представителей крупнейших компаний (Microsoft, Intel, IBM, Google и др.), и каждая новая функция должна быть одобрена большинством. Споры о деталях (например, о реализации export для шаблонов, который в итоге почти не использовался) могли длиться годами.
Обратная совместимость: C++ всегда ставил во главу угла совместимость с существующим кодом. Любое изменение не должно было ломать миллиарды строк уже написанного кода. Это накладывало огромные ограничения и усложняло дизайн новых features.
3. Работа "в фоновом режиме" и TR1
Хотя официального стандарта не выходило, работа кипела. В 2005 году был выпущен Technical Report 1 (TR1). Это был не официальный стандарт, а набор технических спецификаций, который компиляторы начали постепенно реализовывать. Многие компоненты из TR1 вошли в C++11:
Умные указатели (std::shared_ptr, std::weak_ptr)
Регулярные выражения (std::regex)
Хеш-таблицы (которые позже стали std::unordered_map, std::unordered_set)
Кортежи (std::tuple)
Так что разработчики не стояли на месте — они активно готовили почву для грядущего обновления.
4. Смена парадигмы: C++11 как "новый язык"
Комитет осознал, что результат их работы настолько масштабен, что C++11 будет восприниматься как практически новый язык. Бьярн Страуструп говорил, что C++11 "чувствует себя как новый язык". Чтобы сделать его целостным и качественным, потребовалось дополнительное время.
После C++11 комитет перешел на цикл развития "каждые три года":
C++20 (2020) — еще один "прорывной" стандарт (Concepts, Modules, Ranges, Coroutines).
C++23 (2023) — дальнейшее развитие идей C++20.
"Большой перерыв" между C++98 и C++11 не был периодом застоя. Это был период интенсивной, глубокой и сложной работы по созданию фундамента для современного C++. Комитет потратил это время на переосмысление языка, чтобы не просто добавить новые возможности, а сделать это правильно, сохранив его дух и обратную совместимость. Эта пауза окупилась с лихвой, позволив C++ оставаться актуальным и мощным языком программирования в 21 веке.
В принципе, лично я склонен согласиться с такой версией.
ЕМ>- Компилятор в ходе анализа программы собирает множество различных сведений.
Собирает
ЕМ>- Компилятор мог бы отдавать эти сведения непосредственно через какие-нибудь служебные конструкции, но язык упорно избегает их вводить.
Да, язык не хочет вводить какие-то низкоуровневые конструкции. У каждого компилятора под капотом своя кухня, и если её выводить для пользователя, то она ИМХО была бы слишком разношерстной, и несовместимой между компиляторами. Поэтому стандарт описывает более высокоуровневые вещи, а как их реализовывать — через "трюки" или добавлять в компилятор какую-то поддержку — это дело компиляторостроителей. Я тебе приводил пример с std::is_class и прочими, но ты, похоже, не заметил.
ЕМ>- В сложившейся ситуации изобретаются различные трюковые механизмы, косвенными методами добывающие у компилятора эти сведения, причем далеко не все. Но это объявляется годной, достойной практикой, и начинает всячески развиваться.
Какие такие "трюковые" механизмы?
ЕМ>- Одновременно изобретаются трюковые механизмы обобщенного программирования, позволяющие порождать код условно и циклически, но никакой поддержки со стороны языка долгое время даже не планируется, а затем в этом направлении начинается очень медленное, крайне неохотное движение.
Какие такие "трюковые" механизмы?
Медленно — потому что всё детально продумывают, чтобы ничего старого не сломать. А то будет, как с питоном, каждые три года выкатываться несовместимый язык — ну и кому это нужно?
ЕМ>Опять же, с самого начала даже интуитивно понятно, что для устранения фундаментальных недостатков языка нужно вводить в него средства как извлечения сведений из компилятора, так и условного/циклического порождения кода. В том или ином виде такие средства были известны за десятки лет до этого. Вы знаете хоть сколько-нибудь серьезные и вдумчивые обсуждения на тему "что нужно добавить в язык, чтобы избавиться от необходимости использовать трюки, получить непосредственно от компилятора больше сведений за меньшую цену, и указывать непосредственно компилятору, когда порождать тот или иной код, а когда нет"?
Всё равно не понимаю, что конкретно ты называешь трюками, и почему такие способы плохи?
ЕМ>Угу, когда тормозить и тянуть дальше стало уже совсем невмоготу, они начали завозить по паре капель, а Вам, на безрыбье, уже и это за счастье.
Или было не так
S>>А если бы не застой в развитии C++ (о котором вам Marty уже сказал), все эти средства должны были появится в C++ гораздо раньше.
ЕМ>Я уже много раз подчеркивал, что дело не в застое. Дело в очевидно нездоровом подходе "ну как-то ведь получилось, пусть теперь так и будет, нечего от добра добра искать". Любой инженер Вам скажет, что это колхозный, обывательский подход. Ребята-новаторы с очумелыми ручками могут придумывать 100500 способов использования скотча и суперклея для сборки и ремонта водопровода, и даже устраивать всемирные конкурсы по этому делу, но в мало-мальски серьезном производстве так нельзя, фу так делать.
Ты не поверишь, но различные самоклеющиеся материалы вполне себе используются в производстве
Здравствуйте, so5team, Вы писали:
S>Кроме того, языков с настолько массовым использованием и развиваемых настолько большим комитетом, да еще и с результатом в виде ISO-стандарта, как я понимаю, больше нет.
Ну, насчёт комитета не знаю, но ISO есть вроде ещё у JS. Но сам факт наличия ISO, на примере того же JS, не может избавить язык от врождённой пипецомы
S>Из языков со стандартом вспоминается только Си. Но он по возможностям сильно меньше C++, да и то туда _Generic-и засунули.
Здравствуйте, Marty, Вы писали:
S>>Кроме того, языков с настолько массовым использованием и развиваемых настолько большим комитетом, да еще и с результатом в виде ISO-стандарта, как я понимаю, больше нет.
M>Ну, насчёт комитета не знаю, но ISO есть вроде ещё у JS. Но сам факт наличия ISO, на примере того же JS, не может избавить язык от врождённой пипецомы
Поиск в Интернете показал, что у JS не ISO стандарт, а ECMA, при этом со стороны ISO идет "признание" стандарта ECMA для JS.
Т.е. формально у JS нет ISO стандарта.
Ну и насколько я понимаю, в ECMA более быстрая и менее замороченная процедура принятия новых редакций, чем в ISO.