Условная компиляция – это процесс выбора, какой код компилировать, а какой не компилировать, подобно #if / #else / #endif в C и C++. Любой оператор, который ещё не скомпилирован, должен быть синтаксически правильным.
Условная компиляция включает в себя проверки условий, которые можно вычислить во время компиляции. Условные выражения времени выполнения, такие как if, for, while не являются выражениями условной компиляции. Для неё предназначены следующие операторы D:
Оператор debug (отладка) полезен при разработке программы. Выражения и инструкции, помеченные как debug, компилируются в программе только при включённом переключателе компилятора -debug.
debug условно_компилируемое_выражение; debug { // ... условно номпилируемый код ... } else { // ... код, который компилируется в противном случае ... }
Предложение else является необязательным. И одиночное выражение, и блок кода, показанные выше, компилируются только если у компилятора включен параметр -debug.
Вместо того, чтобы вообще удалять строки программы, их можно помечать оператором debug.
debug writefln("%s оператор, действующий только в режиме debug", value);
Такие строки включаются в программу только при наличии параметра компилятора -debug.
dmd test.d -oftest -w -debug
Операторам debug можно присваивать имена (теги), таким образом они будут включаться в программу выборочно.
debug(mytag) writefln("%s не найдено", value);
Такие строки включаются в программу только при наличии параметра компилятора -debug.
dmd test.d -oftest -w -debug = mytag
Операторы debug с блоком кода также могут иметь теги.
debug(mytag) { // }
Допустимо одновременно включать несколько тегов отладки.
dmd test.d -oftest -w -debug = mytag1 -debug = mytag2
Иногда полезнее связывать отладочные выражения с числовыми уровнями. Повышение уровня может предоставить более подробную информацию.
import std.stdio; void myFunction() { debug(1) writeln("debug1"); debug(2) writeln("debug2"); } void main() { myFunction(); }
Будут скомпилированы отладочные выражения и блоки, которые меньше или равны указанному уровню,
$ dmd test.d -oftest -w -debug = 1 $ ./test debug1
Оператор version (версия) похож на debug и используется таким же образом. Предложение else необязательно. Хотя version работает практически так же, как и debug, наличие отдельных ключевых слов помогает различать области их применения. Как и при debug, можно включить больше одной версии.
import std.stdio; void myFunction() { version(1) writeln("version1"); version(2) writeln("version2"); } void main() { myFunction(); }
Будут скомпилированы версионные выражения и блоки, которые меньше или равны указанному уровню,
$ dmd test.d -oftest -w -version = 1 $ ./test version1
Static if – это эквивалент инструкции if времени компиляции. Как и оператор if, static if принимает логическое выражение и вычисляет его. В отличие от оператора if, static if не относится к потоку выполнения; вместо этого он определяет, нужно ли включать фрагмент кода в программу или нет.
Выражение if не связано с оператором is, который мы видели ранее, как синтаксически, так и семантически. Он вычисляется во время компиляции. Его результатом является значение типа int, равное 0 или 1; в зависимости от выражения, указанного в круглых скобках. Хотя принимаемое выражение не является логическим выражением, само оно используется как логическое выражение времени компиляции. Это особенно полезно для условий static if и ограничений шаблонов.
import std.stdio; enum Days { sun, mon, tue, wed, thu, fri, sat }; void myFunction(T)(T mytemplate) { static if (is (T == class)) { writeln("Этот тип – класс"); } else static if (is (T == enum)) { writeln("Этот тип – перечисление"); } } void main() { Days day; myFunction(day); }
Когда вы скомпилируете и выполните эту программу, она возвратит следующий результат:
Этот тип – перечисление