LINUX.ORG.RU

Возможности метапрограммирования в С++

 , ,


0

3

Как в плюсах обстоят дела с метапрограммированием? Например такая задача: есть библиотека длинной арифметики, GMP называется. Даже есть привязка для С++ с перегруженными + - * / и прочими штуками. См https://gmplib.org/manual/C_002b_002b-Interface-General.html#C_002b_002b-Inte...
Так вот, допустим что надо сделать нечто, что делало бы оптимизацию операций с этими вот числами. Пример:

  if (a == 0) error();
  else return (a+a+a+a)/a;
Надо чтобы этот код был преобразован к виду
  if (a == 0) error();
  else return 4;
А например какой-нибудь код
 return a*c+b*c;
становился
 return c*(a+b);
и так далее.
Так вот. Чтобы решать такого рода задачи, придумали https://en.wikipedia.org/wiki/Expression_templates
Однако, код разбора и преобразования выражений в более оптимальный вид получается неуниверсальным - он работает только в компилтайме. Если я захочу в своей программе читать из stdin-а некую формулу, и эту формулу определенным образом преобразовывать, чтобы ее было легче считать, то эти expression templates оказываются совершенно бесполезными(можно разве что попробовать как-нибудь встроить непосредственно в программу кусок компилятора, который ответственен за разбор шаблонов, но это не является приемлемым решением). Так вот, можно ли как-нибудь сделать это универсально, чтобы и на этапе компиляции, и при выполнении я мог использовать ОДИН КОД для арифметических преобразований?
Единственный выход, который я вижу - метапрограммирование через кодогенерацию.

Эх, если был бы какой-нибудь язык программирования без GC, такой же низкоуровневый и быстрый как Си, и с гомоиконностью, чтоб можно было работать с неким абстрактным представлением кода вместо генерации синтаксически правильного Си/С++ кода...

★★★★★

Последнее исправление: SZT (всего исправлений: 2)
Ответ на: комментарий от SZT

Для нормальной кодогенерации в run-time надо делать JIT, а это уже выходит за рамки плюсов и их стандарта.

За рамки стандарта плюсов выходит вообще практически все: файловая система, сеть, IPC, GUI, криптография и еще куча вещей, необходимых для чего-либо более сложного, чем HelloWorld. Тем не менее, люди для плюсов уже давным давно делали run-time кодогенерацию, например, путем использования C++компилятора: генерился C++ный код, пропускался через компилятор и линкер, на выходе получалась, скажем, DLL, которая подгружалась и из которой дергался нужная экспортированная функция. Или же на выходе получался новый исполнимый файл, запускавшийся дочерним процессом и общение с которым происходило через IPC.

Например, упрощать арифметические выражения с bigint-ами. constexpr не позволяют эффективно решать данную задач

Ну так чего вы до них докопались? Кто вам вообще обещал, что constexpr облегчит вам метапрограммирование на C++?

Если же constexpr задумывался лишь как удобный способ просчитать константы на этапе компиляции, то это просто смешно...

Кому смешно, а кто-то пользуется. Например, с помощью constexpr можно реализовать функцию, возвращающую размерность вспомогательного массива, нужного для решения какой-то задачи. Скажем, что-то вроде:

float tmp_array[ calc_temp_array_size(12, 15, 100500) ];
Если calc_temp_array_size() — это constexpr-функция, то мы получаем возможность размещать tmp_array на стеке или в статической памяти. В отсутствие constexpr вы что предлагаете делать? Поржать и оформить calc_temp_array_size макросом?

Усилия, затраченные на реализацию этого constexpr во всех актуальных C++ компиляторах, просто несоизмеримы с полезностью данной фичи, если ее предполагается использовать только лишь для констант.

Откуда дровишки? Участвовали в разработке GCC, Clang, Intel C++ или Microsoft С++?

eao197 ★★★★★
()
Ответ на: комментарий от DarkEld3r

Затащат в стандарт ведь?

Очень и очень надеюсь на это.

насколько у тебя терпения хватит

Вряд ли надолго.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Если calc_temp_array_size() — это constexpr-функция, то мы получаем возможность размещать tmp_array на стеке или в статической памяти. В отсутствие constexpr вы что предлагаете делать?

Предлагаю сделать код, который

printf("%" PRIu64 "\n", calc_temp_array_size(12, 15, 100500) );
Потом
./a.out > arrsz.h
float tmp_array[ 
                 #include "arrsz.h"
               ];
При желании это все можно автоматизировать каким-нибудь препроцессором, чтобы можно было делать
float tmp_array[ 
                 /*## EXEC(printf("%" PRIu64 "\n", calc_temp_array_size(12, 15, 100500) ); */
               ];

Откуда дровишки? Участвовали в разработке GCC, Clang, Intel C++ или Microsoft С++?

А вы прикиньте, что надо сделать в том же GCC чтобы обеспечить возможность обрабатывать эти constexpr-ы в компилтайме, учитывая еще тот факт, что это может быть кросскомпилятор, который скажем на интеле работает, а код генетирует под какой-нибудь AVR 16-битный. А сделать надо ИНТЕРПРЕТАТОР этого C++

SZT ★★★★★
() автор топика
Последнее исправление: SZT (всего исправлений: 1)
Ответ на: комментарий от SZT

А вы прикиньте, что надо сделать в том же GCC чтобы обеспечить возможность обрабатывать эти constexpr-ы в компилтайме

А ты прикинь, gcc и так это умел в рамках оптимизаций. constexpr по факту больше нужен программисту, чтоб объяснять ему, почему его код не будет соптимизирован на этапе компиляции.

учитывая еще тот факт, что это может быть кросскомпилятор, который скажем на интеле работает, а код генетирует под какой-нибудь AVR 16-битный. А сделать надо ИНТЕРПРЕТАТОР этого C++

Ты упорот, кросскомпиляция тут вообще никаким боком не влияет.

anonymous
()
Ответ на: комментарий от anonymous

А ты прикинь, gcc и так это умел в рамках оптимизаций.

Нет. Компилятор в рамках оптимизации без constexpr тебе не будет сортировку пузырьком считать
http://goo.gl/1XBfzO - без constexpr
http://goo.gl/K2DVjC - c constexpr

SZT ★★★★★
() автор топика
Ответ на: комментарий от SZT

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

Вот для того, чтобы через 30 лет после появления C++ на свет не приходилось все это делать и дружить всю эту pre-compile-time байду с разными системами сборки, IDE, статическими анализаторами и прочим инструментарием, и сделали в языке поддержку constexpr — один раз в коде написал и никаких заморочек.

А вы прикиньте, что надо сделать в том же GCC чтобы обеспечить возможность обрабатывать эти constexpr-ы в компилтайме

Проблемы негров шерифа, вообще-то, не волнуют. Мне как-то фиолетово, сколько сил вложили разработчики GCC в поддержку constexpr. Раз такую фичу через комитет продавили, значит она изначально выглядела реализуемой. И то, что со временем компиляторы становятся более сложными и поддерживают все более и более навороченные языковые конструкции — это нормально, т.к. прогресс не стоит на месте и всякое такое...

eao197 ★★★★★
()
Ответ на: комментарий от SZT

Нет. Компилятор в рамках оптимизации без constexpr тебе не будет сортировку пузырьком считать

Потому-что там, очевидно, есть ограничения на глубину вычислений, чтоб компилятор на оптимизациях не подвисал на неопределенное время. А с constexpr он просчитывает все без ограничений - так пользователь попросил. Вообще еще в 2001-м году gcc умел сворачивать вычисления с if/goto/...:

https://gcc.gnu.org/news/ssa-ccp.html

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.