Как стать автором
Обновить

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

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

Если на шаблонах и функциях рекурсия пишется естественным способом (компилятор берёт на себя арифметику и ветвление), то на препроцессоре придётся как-то исхитряться.


Вот, казалось бы, BOOST_PP, практически промышленная библиотека, — а и то имеет внутренние ограничения "потомучто марамучто". Там нельзя сделать препроцессорный массив из более чем 20 элементов, потому что у разработчиков на 21-м нумерованном макросе контрол-вэ сломалось.

Могли бы сделать нормальные синтаксические макросы. Да хоть встроить в компилятор любой скриптовый язык — хоть тот же JavaScript — и сделать API к синтаксическому дереву.
Кодогенерация это интересно, но если для написания кода на одном языке вам нужен код на другом языке — это повод задуматься, а всё правильно ли Вы делаете.

У каждого языка своя ниша и специализация. C++ явно небезопасен для того, чтобы на нем писать плагины к компилятору. А у js уже есть успешный опыт работы с древовидной DOM языка HTML.
Те же шаблоны C++ это по сути отдельный язык, лишь частично пересекающийся с C++. Вы не примените там if, while, for, не выделите память оператором new, не воспользуетесь классами какого нибудь Qt или WxWidgets.
Проблема а том, что этот язык получился случайно и не очень то удобен для программирования.

Полностью с вами согласен. Я про то, что нужно разделять сущности. Т.е. здесь мы не пишем код, а работаем с AST. Ну и инструменты надо брать соответствующие: или пользоваться языками, в которые прямая манипуляция с AST заложена, например, лисп или тикль, или писать плагин для компилятора, или глумиться над рантаймом. А вот написание кода и работу с его представлением в одном файле смешивать как-то не стоит.

Я плохо говорю на плюсах, но в С на макросах можно реализовать if, while, for в boost.preprocessor или в Р99. Хотя это жуткое извращение заставлять фактически рефал-машину изображать из себя императивный ЯП.

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

Ох, если бы рефал-машину…
У меня такие ассоциации: иммутабельность, чистота, подстановка. Собсно, из-за изначально заложенных подводных граблей при любой реализации for на макросах вылазит ужас типа
#define EVAL1024(x) (EVAL512(x), EVAL512(x))
а while разворачивается в аналог prototheads/Duff's device через макросы FOR (см.выше) и __line__
Вот если бы в качестве обязательного этапа трансляции был не cpp, а m4
Спасибо, мы ещё помним sendmail. Аж по шкварнику мурашки пробежали.

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


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

У вас в коде ошибка:
constexpr unsigned f(unsigned n) {
  return n < 2 ? f(n-1) + f(n-2);
}

Ага, спасибо, поправил. В работающем коде, разумеется, этого уже нет :)

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

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


#include <iostream>

char f(...);
const int a = sizeof(f(0));  // 1
short f(short);
const int b = sizeof(f(0));  // 2
int f(int);
const int c = sizeof(f(0));  // 4

int main() {
  std::cout << a << " " << b << " " << c << std::endl;
}

Определение функции закрепляет контекст: где она определена, там она и будет вычисляться.
А два экземпляра одного и того же выражения, скопированные в разные места… следует рассматривать как два выражения, хоть и побуквенно совпадающие.

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

Публикации

Истории