add section about conditional compilation

This commit is contained in:
Johannes Loher 2018-06-07 23:08:10 +02:00
parent 2d43ed3eda
commit 1773b32d94

View file

@ -545,7 +545,7 @@ flag `--boundcheck=off`.
#### Static arrays #### Static arrays
Static arrays are stored on he stack or in static memory, depending on where Static arrays are stored on he stack or in static memory, depending on where
they are defined. They have a fixed, compile-time known length. The length is they are defined. They have a fixed, compile time known length. The length is
part of the type: part of the type:
```D ```D
@ -1357,8 +1357,8 @@ the `-cov` flag. When using DUB, just add the flag `--coverage`.
### String mixins ### String mixins
The mixin expression takes an arbitrary string and compiles it and generates instructions accordingly. This is a compile-time feature, so ths string needs The mixin expression takes an arbitrary string and compiles it and generates instructions accordingly. This is a compile time feature, so ths string needs
to be known at compile-time. to be known at compile time.
```D ```D
mixin("int b = 5"); // compiles just fine mixin("int b = 5"); // compiles just fine
@ -1369,7 +1369,7 @@ mixin(compileTimeKnownString); // so does this
assert(c == 5); assert(c == 5);
immutable runTimeString = q{int c =5;}; immutable runTimeString = q{int c =5;};
mixin(runTimeString); // compile error, runTimeString is not known at compile-time mixin(runTimeString); // compile error, runTimeString is not known at compile time
``` ```
### Compile Time Function Evaluation (CTFE) ### Compile Time Function Evaluation (CTFE)
@ -1412,4 +1412,98 @@ void main() {
writeln("The sqrt of compile time 4 = ", writeln("The sqrt of compile time 4 = ",
cn); cn);
} }
```
### Conditional compilation
D has several methods of conditional compilation which can be used for code
generation. Ds traits and the module `std.traits` contain many usefull tools
which can be used with the following constructs.
#### `static if` & `is`
`static if` conditionally compiles a code block based on a condition that can be
evaluated at compile time:
```D
foo(int x)() { // x is a template parameter and thus known at compile time
static if(x == 0)
writeln("x is 0");
else
writeln()
}
```
The `is` expression is used to check for valid types and to compare types:
```D
foo(T)() {
static if(is(T)) {
writeln("T is a valid type");
}
static if(is(T == int)) {
writeln("T is int");
}
static if(is(T : int)) {
writeln("T implicitly converts to int");
}
}
```
#### `static foreach`
`static foreach` allows you to iterate at compile time in order to generate
code. It is best explained by an example: The code
```D
import std.stdio;
void main() {
static foreach(element; ["foo", "bar", "baz"]) {
writeln(element);
}
}
```
effectively lowers to
```D
import std.stdio;
void main() {
writeln("foo");
writeln("bar");
writeln("baz");
}
```
which means there is no loop at runtime.
#### Template constraints
A template may be defined with any number of constraints that enforce some
properties of the template parameters:
```D
void foo(T)(T value)
if (is(T : long)) { // foo!T only valid if T implicitly converts to long
}
foo(42); // compiles, 42 is of type int which implicitly converts to long
foo("someString"); // compile error, strings do not implicitly convert to long
```
```D
void bar(T)(T value)
if (__traits(compiles, {T t = T.init; t.fly();})) { // bar!T only valid if we can initialize T and T has a method called fly which takes no parameters
}
struct MyStruct {
void fly() {}
}
MyStruct myStruct;
bar(myStruct); // compiles
bar(42); // compile error
``` ```