add section about conditional compilation
This commit is contained in:
parent
2d43ed3eda
commit
1773b32d94
1 changed files with 98 additions and 4 deletions
|
@ -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)
|
||||||
|
@ -1413,3 +1413,97 @@ void main() {
|
||||||
cn);
|
cn);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Conditional compilation
|
||||||
|
|
||||||
|
D has several methods of conditional compilation which can be used for code
|
||||||
|
generation. D’s 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
|
||||||
|
```
|
Loading…
Reference in a new issue