Pull to refresh

Comments 55

Очень интересный способ. Но на его написание (ИМХО) уйдёт больше времени, чем на вычисление массива первой функцией и его вывода в буфер обмена.
↑Ненормальное программирование↑
Ну, на написание данной вещи действительно ушло много времени. Но теперь есть навык, такое же можно писать очень быстро. Но, как вы правильно замтеили, это же блог «Ненормальное программирование».
Когда от приложения требуется добиться высокой производительности, то проще программисту потратить n-ое кол-во времени, чем приложение потратит на его выполнение в целом. Давно использую данный подход в php, очень доволен. Правда не знал как он называется. Хотя конечно на С++ реализовать такой подход значительно сложнее.
А чем это выгодно? Программа стартует на несколько миллисекунд быстрее, зато нагородили кучу темплейтов ради такой простой вещи.
Эти темплейты закрываются внутри пространства имен и снаружи не видны. Вообще говоря это — proof of concept, ничего более.
а более реалистичный пример можно? с одно стороны метапрограммирование — это прекрасное упражнение для мозгов, но с другой — я не понимаю, где оно может дать серьезные бенефиты.

у template metaprogramming есть на мой взгляд лишь один плюс перед подходом основанном на кодогенерации: шаблоны являются частью языка. На мой взгляд этот плюс убивается мозговзрывающей сложностью более или менее серьезного шаблона.
Имхо, это самый реалистичный пример, который я нашел. Не могу вспомнить другие распространенные примеры, где нужен precomputing.
UFO just landed and posted this here
Прерасный пример! :) Замечательный!
И дело не в том, сколько ДАННЫЙ пример выигрывает или сколько ДАННЫЙ пример экономит.
Это замечательный пример того, как вычисления можно перенести на стадию компиляции!
Класс! Отдельное спасибо автору за указание книги, где о таком пишут.

Правда, страшно представить отладку такого нагромождения темплейтов. Там одну букву не так поставишь, оно такого насчитает… и внутрь не заглянешь step-by-step, ещё и темплейты с их способностью выдавать 20 errors на одну опечатку. Программирование тут, может, и ненормальное, но отладка (особенно, если применить для чего-то более сложного) уже за гранью ненормального. «Madness? This is SPARTAAA!!!» :)
Жесть!!! Мы в микроконтроллерах все CRC табличным способом считали, да еще и выискивали где бы микросекунду сэкономить :-)
UFO just landed and posted this here
На самом деле всё выглядит столь ужасно потому, что метапрограммирование в C++ не добавили, а открыли. Случайно. В языках где про него изначально думали (D, Scala, разнообразные диалекты Lisp'а) всё горазло менее страшно. Но принцип тот же: программа порождает программу.
UFO just landed and posted this here
Ну там добавят немножко новых возможностей. Основная, cамая вкусная, фича классических языков с поддержкой метапрограммирования всё так же далека: язык метапрограммирования не является вариантом языка программирования. Он совершенно иной! А должен быть тем же — ну пусть с небольшими ограничениями. Вот тогда метопрограммирование становится удобным инструментом, а не игрушкой для фанатов…
В Scala (пока) нет метапрограммирования.
люблю такой стиль программирования (вернее ненавижу:) пришлось как-то развивать/улучшать систему для расчетов генераторов для ветрянных электростанций. Генераторов таких (медленновертящихся, без «коробки передач») никто не делал, программист-дипломант до меня наворотил там целый язык из макросов и шаблонов для описания формул. Бедные инженеры для изменения формулы правили код, потом компилировали его (занимало примерно 10 минут) а потом тестировали свою формулу. И так весь день, ругались постоянно, так как настройка была сплошной потерей времени. Ну и мне пришлось повозиться, беда.

В общем, в этом деле нужно чувство меры, и не всегда время потраченное на компиляцию оправдывает быстроту работы программы, не говоря уже о проблеме «ремонтопригодности» такой штуки.
Это да. Такие вещи, серпя сердце, можно применять только в хорошо известных алгоритмах — как в данном случае. Сам бы за такое давал по пальцам. Но эти знания, почерпнутые из книги Александреску, подвигли меня на изучение хотя бы основ функционального программирования, и эти знания мне очень пригодились при переходе на C# 3.5, LINQ, лямбды и иже с ними.
Ага, функциональное программирование это вещь:) Но лично для меня даже в лиспе (а именно доктор схеме) ламда была не совсем «читабельна».
На данный момент реализация в груви мне лично нравится больше всего, синтакс (лично мне) хорошо понятен, хотя на данный момент я с груви не работаю.
а SICP уже читали?
на русском можно скачать здесь — sicp.sergeykhenkin.com/
Интересное решение, а как изменилось время компиляции?
Естественно упала. На пару-тройку секунд.
Как раз после прочтения книги Александреску появилось чуство что С++ не мое.
Потому что жутко не нравится время компиляции и совсем не радует его увеличение библиотеками Loki, Boost. С STL приходиться мириться.

После довольно жуткого проекта с временем полного ребилда пять минут и убитой архитектурой (ребилдить приходилось часто) переметнулся к динамическим языкам.
Теперь занимаюсь Python, Ruby, PHP, JavaScript.

PS: Кодогенерация есть в Qt — qmake. Интересно почему такие системы не получили распространения?
Имхо, кодогенерация шаблонами не гибка, многословна и даже не кеширует результат.

PSS: Python + Qt — отличная связка.
А я сижу на динамических языках и очень грущу о С++ и C# :)

Кстати, а зачем вообще нужен полный ребилд? У нас так только night builds собирались для автотестов.
Делаете так:
— создаете один большой хидер, в который включаете все хидеры проекта
— маскируете невнятным раскидыванием функциональности и ложным именованием

Готово! Теперь при попытках развивать проект будет ребилдится весь проект.
Кстати да, тоже советую всем почитать книгу Андрея Александреску «Современное проектирование на С++».
К счастью, у большинства людей эта книга отбивает желание писать сложные шаблоны :) Зато дает навык их понимания.
Книга сложная, но правильная. И кроме сложных случаев метапрограммирования, там есть еще отличные примеры более простых шаблонов, например Policy-based дизайн классов.
Да, меня в свое время поразили возможности, открываемые шаблонами в C++. Пример замечательный.
Помнится, игрался я в школе с метапрограммированием
www.everfall.com/paste/id.php? c29q3eov4cjj — определитель матрицы N*N compile-time
www.everfall.com/paste/id.php? zakx0n2nwaaa — мультиметоды (для N <= 32 аргументов, а не только для 2)

Вообще, язык метапрограммирования в Си++ — чистый функциональный, но, к сожалению, без карринга и лямбд.
В новом стандарте должны ввести concept/concept_map — в чистом виде type classes из Haskell
Твои примеры — это страшно. В продакшн-коде такое увидеть — не дай бог.
Я ж не дурак такое в продакш совать
Просто интересно было, насколько это реально
Метапрограммирование слабо применимо в коммерческой разработке, если конечно же код пишет не Александреску :)
— Это увеличивает время компиляции. Т.е. сначала я трачу деньги компании на поиск не тривиального решения времени комспиляции, затем я трачу деньги компании на перекомпиляции всего этого добра.
— Это увеличивает сложность проекта, т.е. после ухода человека проектировавшего ЭТО, сложно будет найти настолько же подкованного.
— Применение подобных приемов в языке, который не был спроектирован для этого — не самое лучшее занятие.

Более того, это действительно не продуктивно. Я прочел Александреску два раза, причем оба раза некоторые вещи я читал до посинения и полного понимания. В итоге через два года я практически ничего не помню, и понимания кода выше мне дается с большим трудом, может потому, что было мало практики. Но для сравнения, QT после года использования я не забыл и прекрасно помнил. Так что сложность таки сказывается.
А вот пример для определения простых чисел: sharpc.livejournal.com/23950.html

Только, хочу обратить внимание на слова автора и свой личный опыт: если «разворачивание» метаконструкций будет достаточно долгим, то компилятор выдаст ошибку.
Ты выбрал не самый эффективный способ. Перебор можно ограничить до sqrt(N), уменьшишь количество шаблонов.
(вернее, прекомпилятор)


Какой такой «прекомпилятор»?
сомневаюсь, что препроцессор таким занимается.
Та часть компилятора, которая отвечает за шаблоны и константы. :)
Именно он этим и занимается.
да ну? может потрудитесь доказать?

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

у препроцессора свой метапрограмминг :)

#define tType uint64_t
#define tName(n) myname_#n
#include «t/MetaProg.tpl»

… t/MetaProg.tpl
struct tName(mystruct) {
tType x;
};
void tName(myfun)() {
что-нибудь делаем;
}
#undef tType
#undef tName
ага, ага, Boost.Preprocessor и прочие радости жизни.

но к вычислению константных выражений это всё отношения не имеет.
Класс! Побольше бы именно таких топиков, а не «Oh shi, это же новый айфон!».
Автор, спасибо Вам.
UFO just landed and posted this here
Александреску — просто немного другая книга. Она же не только метапрограммированию посвящена.
А книга by Abrahams, Gurtovoy — это чистое метопрограммирование, причём явно с упором на Boost.MPL (что логично и правильно, они ведь авторы библиотеки).
Спасибо, занимательно. Но если мне не изменяет мой склероз, конкретно этот пример соптимизирует компилятор ((= По крайней мере GCC.
Отличный пост! Хорошо что не перевелись ещё computer science! Скажем да шаблону и нет былокодингу :)

«цикла, повторяющего вычисления «рекурсивно» 7 раз» — исправьте
Еще одно уточнение: таблица все же заполняется в runtime, но значения таки считаются на этапе компиляции. Статья понравилась, спасибо.
Таблица тоже заполняется в компайлтайм, потому как инициализация константная и инлайнится.
Видимо, я невнимательно ищу… Где именно там «константная инициализация»?
Мм. Действительно. Давно писалось — мне казалось, что я проверял, что таблица заполняется в компайл-тайм. Нет под рукой дизассемблера проверить.
ОМГ!

P.S.
За код и пояснения — примите благодарность :)
Самое интересное, что GCC и Comeau это не компилируют. Они считают что:
identifier «values» is undefined
Table() { values[t]=Hash:: value; }
Sign up to leave a comment.

Articles