Альтернативы шаблонам C ++? - PullRequest
6 голосов
/ 28 января 2010

Я думаю, что метапрограммирование очень круто. В частности, я люблю макросы LISP.

Тем не менее, я думаю, что шаблон C ++ отстой, потому что:
1. они замедляют время компиляции (даже с предварительно скомпилированными заголовками, размер которых в итоге составляет 50 МБ, если вы включите любой из них в STL) 2. они дают ужасные ошибки компилятора / синтаксиса, которые являются интуитивными
3. в первую очередь они не были предназначены для сложного метапрограммирования (генерация ошибок компилятора для простых чисел / показ шаблонов завершились очень давно) * 1006

Сказав все это, есть ли достойная альтернатива метапрограммированию на C ++? что-то вроде

*. M -> мета-компилятор -> * .cpp -> g ++ -> исполняемый файл?

EDIT:

Я работаю по принципу «пользовательских сценариев генерации кода». Мне просто интересно, есть ли действительно хороший набор из них там.

Ответы [ 5 ]

7 голосов
/ 28 января 2010

Я не уверен, что это то, чего нужно, я использовал генераторы кода для создания кода C ++. В частности, питонские гепарды. Вы в основном встраиваете прямой код Python в код C ++ и запускаете его через preprocessor.it cheetah, что позволяет выполнять довольно сложные вычисления гораздо проще, чем с помощью шаблонов или препроцессора C ++, плюс вы получаете все библиотеки и расширения Python. с другой стороны, это затрудняет отладку, если что-то пойдет не так. Если вы заинтересованы, я мог бы предоставить несколько примеров и режим Emacs для редактирования программ на гепарде C ++.

Если вам нужно что-то менее мощное и вы хотите остаться только в C ++ C, взгляните на препроцессор boost, здесь . Требуется немного времени, чтобы привыкнуть к нему, но это может сделать жизнь по-настоящему легкой, если задействован повторяющийся код

хорошо, я вставляю пример с гепардами, дай мне несколько минут:

#if defined (__INTEL_COMPILER)
#pragma vector aligned
#endif
        for(int a = 0; a < $N; ++a) {
            /// for functions in block
%for ii, (fi,fj) in enumerate(fb)
%set i = ii + ifb
/// can also use (ix,iy,iz)=fi[0:2], need to clean up when not lazy
%set ix = fi[0]
%set iy = fi[1]
%set iz = fi[2]
%set jx = fj[0]
%set jy = fj[1]
%set jz = fj[2]
            q$(i) += Ix(a,$(ix),$(jx))*Iy(a,$(iy),$(jy))*Iz(a,$(iz),$(jz));
%end for
            /// end for functions in block
        }

производит (после запуска cheetah ...)

#if defined (__INTEL_COMPILER)
#pragma vector aligned
#endif
        for(int a = 0; a < 6; ++a) {
            q0 += Ix(a,0,1)*Iy(a,0,0)*Iz(a,0,0);
            q1 += Ix(a,1,1)*Iy(a,0,0)*Iz(a,0,0);
            q2 += Ix(a,0,1)*Iy(a,1,0)*Iz(a,0,0);
            q3 += Ix(a,0,1)*Iy(a,0,0)*Iz(a,1,0);
            q4 += Ix(a,0,0)*Iy(a,0,1)*Iz(a,0,0);
            q5 += Ix(a,1,0)*Iy(a,0,1)*Iz(a,0,0);
            q6 += Ix(a,0,0)*Iy(a,1,1)*Iz(a,0,0);
            q7 += Ix(a,0,0)*Iy(a,0,1)*Iz(a,1,0);
            q8 += Ix(a,0,0)*Iy(a,0,0)*Iz(a,0,1);
            q9 += Ix(a,1,0)*Iy(a,0,0)*Iz(a,0,1);
        }

, который является обычным кодом C ++

строки, начинающиеся с%, интерпретируются препроцессором cheetah как операторы python. /// комментарии гепарда. По умолчанию # используется как операторы python, но я изменил их, чтобы избежать коллизий с директивами препроцессора Си. %end должен использоваться для завершения блоков Python. Переменные в коде C ++, которые начинаются с $, заменяются переменными python.

Хотите примеры использования препроцессора boost?

3 голосов
/ 26 февраля 2010

Большинство людей настаивают на попытке метапрограммирования изнутри их любимого языка. C ++ считается наиболее существенным примером из-за метапрограммирования шаблонов. Хотя это работает, это больно и неуклюже. Я нахожу это говорящим людям, понявшим, что он способен к Тьюрингу, после того, как Страустроп добавил его в язык; Я не думаю, что даже он ожидал, что все получится так, как он сделал, хотя я сомневаюсь, что он сейчас будет жаловаться на это.

Но большинство языков программирования не имеют средств метапрограммирования. (Или они могут иметь слабые или неуклюжие способности:)

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

Если у вас есть система преобразования программ общего назначения, которая может анализировать произвольные языки, вы можете затем выполнять метапрограммирование на / на любом языке, который вам нравится. Смотрите наш DMS Software Reengineering Toolkit для такого инструмента, который имеет надежные интерфейсы для C, C ++ (даже C ++ 17), Java, C #, COBOL, PHP и ряда других языков программирования, а также был использован для метапрограммирования на всех этих.

Этот подход полезен, поскольку он обеспечивает регулярный методологический подход к предоставлению методов метапрограммирования для любого языка, которым вы хотите манипулировать. И вам не нужно ждать, пока разработчики и разработчики языка будут реализованы, и при этом вам не придется мириться с ограничениями того, что они могут себе представить или фактически реализовать, или платить за пространство / время времени исполнения всех этих отражающих данных, которые ему требуются. поддержать его.

И преобразование программы более мощное, чем метапрограммирование шаблонов C ++ , несмотря на то, что TM поддерживает Turing! Причина в том, что TM может генерировать произвольный код из шаблонов, но не может изменять не шаблонный код. Программные преобразования могут имитировать TM, если вы настаиваете, и, по крайней мере, столь же сильны, но могут также выполнять произвольные изменения в не шаблонном коде. Таким образом, строго более мощный.

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

(Мы провели архитектурный реинжиниринг очень больших приложений C ++ с использованием DMS. TM просто не может этого сделать).

1 голос
/ 28 января 2010

Генерация кода - лучший ответ ...

Вы также должны посмотреть, как ядро ​​Linux создает связанные списки.

Объясненный список ядра Linux

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

1 голос
/ 28 января 2010

Если вы используете C ++, я думаю, что единственными приемлемыми альтернативами являются либо прямые макросы препроцессора , либо пользовательские генерация кода .

описанный вами рабочий процессв основном это некоторая форма генерации кода, в которой вы должны предварительно обработать ваш файл .m в скомпилируемый код C ++. SWIG - действительно хороший пример проекта, который делает это.

Лично я имел большой успех в написании генераторов кода на Python, но я думаю, что любой язык сценариев был бы столь же хорош,Один пакет, который может быть полезен - cog от нашего собственного Нед Бэтчелдера :)

0 голосов
/ 23 октября 2011

Если C ++ 0x является опцией, то некоторые проблемы метапрограммирования шаблона могут быть сведены к набору функций constexpr, выполняемых во время компиляции. Например, рассмотрим сопоставление регулярных выражений во время компиляции с использованием constexpr . Функции constexpr также быстрее , чем метапрограммы C ++.

Если вы занимаетесь функциональным программированием, также доступны несколько других опций.

Шаблон C ++ для метапрограммирования со встроенным Haskell

Мета к функциональному стилю интерфейса для метапрограмм шаблона C ++

Документы Абеля Синковича

...