Примеры использования шаблонов D для

Я слышал, что язык D имеет мощные функции метапрограммирования для выполнения функций во время компиляции. Это звучит очень захватывающе, но мне трудно думать о практических примерах вещей, которые трудно сделать без них.

Кто-нибудь может привести примеры ситуаций, когда функции метапрограммирования D оказываются очень полезными?

21
задан BCS 29 August 2010 в 04:15
поделиться

4 ответа

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

Вот простой пример обработки файла во время компиляции.

main.d

string make_ints(string s)
{
    string ret = "";
    foreach (varname; split(s))
        ret ~= "int " ~ varname ~ "; ";
    return ret;
}

void main()
{
    mixin(make_ints(import("script")));
    foo = 1;
    bar = 2;
    xyz = 3;
}

script

foo bar xyz

Во время компиляции файл «script» будет прочитан, разделен пробелами, а затем make_ints вернет int foo; int bar; int xyz; прямо в код D, готовый к использованию этих переменных.

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

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

21
ответ дан 29 November 2019 в 06:56
поделиться

Если вам нужны практические примеры того, как Чтобы использовать возможности метапрограммирования D (CTFE, или оценка функции времени компиляции, это лишь одно из них, но даже не самое важное), не ищите ничего, кроме Phobos, стандартной библиотеки D2. Большая часть этого кода написана Андреем Александреску, который изобрел множество методов метапрограммирования шаблонов на C ++, и теперь работает с Уолтером Брайтом над дизайном и реализацией D.

Лучшими модулями для поиска являются std.range и std.algorithm . Они почти полностью состоят из шаблонов, были разработаны Андреем и удивительно удобочитаемы, учитывая количество используемых в них метапрограммирований. Я внес значительный вклад в оба этих модуля, и в основном я научился читать код, который был там, когда я начинал.

Весь код находится под (чрезвычайно разрешительной) лицензией Boost и может быть просмотрен прямо из вашего браузера на сайте Phobos Trac на dsource.org.

Чтобы дать вам представление о том, на что вы смотрите, средства метапрограммирования D в основном делятся на 4 категории:

  1. Шаблоны , которые в основном похожи на шаблоны C ++, но с некоторыми добавленными функциями, такими как static if , static assert , вариативные шаблоны и ограничения, которые в основном похожи на концепции, но проще.

  2. Размышление / самоанализ во время компиляции .Сюда входят встроенные выражения is () и __ traits , а также стандартный библиотечный модуль std.traits.

  3. Миксины . Они позволяют вам взять либо шаблон (миксины шаблонов), либо строку времени компиляции (миксины строк) и оценить их как код в текущей области. Строковые миксины можно рассматривать как нечто вроде оператора eval, за исключением того, что строка оценивается как код во время компиляции, а не во время выполнения.

  4. Оценка функции времени компиляции, или CTFE , который позволяет выполнять оценку функций, соответствующих определенным критериям, во время компиляции. Одним из важных применений CTFE является то, что в сочетании со строковыми миксинами вы можете сгенерировать код в виде строки во время компиляции, а затем оценить его как код в области, в которой встречается оператор mixin . Примеры этого см. В std.range.Lockstep и std.range.OutputRangeObject, которые я недавно проверил в SVN-версиях Phobos.

21
ответ дан 29 November 2019 в 06:56
поделиться

Я плохо разбираюсь в целях метапрограммирования. Вот мой взгляд на три основные конструкции, найденные в D.

  • Оценка функции времени компиляции связана с производительностью. Заставить компилятор выполнять как можно больше работы, чтобы после фактического запуска программы выполнялось меньше.
    • Например, создание кэша простых чисел, если ваша программа часто их использует.
  • Шаблоны предназначены для устранения дублирования алгоритмов. Это не просто универсальное программирование, но, поскольку в D есть CTFE, он не нужен в тех же случаях, что и C++.
  • Примеси позволяют генерировать код во время компиляции, который добавляется в программу. Он опирается на такие вещи, как шаблоны и CTFE, но все же является важной частью, не предоставляемой другими.
5
ответ дан 29 November 2019 в 06:56
поделиться

Наиболее интересное практическое применение, о котором я знаю, это библиотека, которую я написал* для использования средства проверки типов для обеспечения безопасности единиц (то есть запрещающего добавление расстояний в разы и обеспечивая правильное преобразование при добавлении метров в футы). То же самое можно сделать и было сделано в C++, но сделать это в D во время компиляции немного сложнее, чем во время выполнения.

* извините за беспардонный плаг.

5
ответ дан 29 November 2019 в 06:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: