Как стать автором
Поиск
Написать публикацию
Обновить

Метапрограммирование 2.0: макросы и генерация кода в современном мире

Уровень сложностиСредний
Время на прочтение9 мин
Количество просмотров9.4K
Всего голосов 58: ↑57 и ↓1+76
Комментарии16

Комментарии 16

Ещё одна проблема — «невидимые зависимости»: генераторы кода могут скрывать логику от IDE, ломая автодополнение и рефакторинг.

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

развернуть код с включениями можно при помощи clang-tools там надо посмотреть(она есть там инклюды показывает и тд), какая тула развернёт, далее при обращении к lsp решению (я не в вс код смотрел)(тут поможет немного магии, дело в том что lsp может показать как компилирует, парадокс в том что он для отрисовки), делая текстовый редактор смотрел как реализовать подсказки и как-бы столкнулся с ситуацией )) можно посмотреть как компилируется, ну и там надо в тулах посмотреть есть еще cov и прочее, правда для этого придётся собирать кланг(всё это конечно не до конца покажет что там внутри)

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

--
ну а можно просто -v прописать тоже что-то покажет как компилирует, как это применить в визуалке не знаю возможно поможет cl --help

json пока не буду использовать, dsl пусть она сама генерит если ей надо с АСТ я пока акцентируюсь на оснастках и показать как собирается и тп, мне лсп не совсем и нужен при условии если он в терминале будет, если заработает как я предпологаю

просто в java комплит кода дорогой очень и клангд дорогой если понаблюдать

у меня будет решение наоборот наверно, я сужу по емаксу и еклипсу, и там и там висит клангд и много памяти потребляет

НЛО прилетело и опубликовало эту надпись здесь

С pack_t TMP на этапе компиляции перебирает поля, сортирует их по выравниванию и генерирует упакованную структуру размером 8 байт вместо 12

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

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

struct логически предполагает однозначный порядок

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

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

А на порядке полей в struct, в частности, держится бинарный ввод-вывод (т.е. в конечном итоге весь ввод-вывод, так как текстовый – надстройка над бинарным).

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

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

Я не говорю уж о том, что не в любой архитектуре ОС файл является потоком байт.

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

А не надо использовать произвольные довольно сложные форматы на нижнем уровне.

А вы как справляетесь с рутиной в коде? Используете макросы, аннотации или полагаетесь на умных помощников?

Стираем сложный и непонятный код, и заменяем его простым. KISS ещё никогда не подводил.

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

Пару примеров:

Предлагаю перейти к «value-based» подходу, о котором говорилось в 2024–2025 годах на CppCon. Всё строится вокруг простой идеи: каждому типу T соответствует уникальное constexpr-значение, и дальше мы работаем с обычными массивами и диапазонами, а не с std::tuple и std::conditional_t.


Я не смотрел CppCon, и поэтому мне не понятна применимость подхода. То есть, вроде и идея понятна, и код понятен, но не хватает практических примеров использования.

Или вот:

С pack_t TMP на этапе компиляции перебирает поля, сортирует их по выравниванию и генерирует упакованную структуру размером 8 байт вместо 12. И снова без рекурсивных шаблонов, а чистый constexpr код.


Явно не хватает имплементации pack_t (или я её не увидел?🤔).

И так далее (по крайней мере в секции C++ и Rust). То есть объяснения вроде и есть, но для не погружённых в специфику решаемых проблем их недостаточно, опять же, на мой взгляд.

P.S. Я не могу сказать, что я эксперт, однако сам я немного писал метапрограммы (один из примеров). И у меня сложилось впечатление, что я решаю очень узкие, и в целом, не очень значительные проблемы, затрачивая колоссальное количество сил и времени. И это и не плохо, если не злоупотреблять этим. Однако, так как проблемы узкие, не всегда просто объяснить какую проблему ты решаешь своим кодом другому программисту.

Скажем прямо, C++ – язык с очень слабенькими макросредствами, и макрогенерация в нём нацелена на затыкание дырок в синтаксисе и семантике языка, а не так чтобы вот на "генерацию кода".

По другому и не могло бы быть, так как макроязык в C++ является небольшим подмножеством основного языка, а третьего и далее уровней быть в принципе не может за отсутствием eval.

Эту статью писал ллм

А вы как справляетесь с рутиной в коде? 

Используем Haskell как макросы на стероидах для C99 в ембеддед.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий