Skip to content

Commit

Permalink
Add gems/template meta programming.md (#24)
Browse files Browse the repository at this point in the history
* Update install-d-locally.md

* Update links-documentation.md

* Add basics/loops.md (#30)

* Add basics/foreach.md (dlang-tour#31)

* Add basics/further-reading.md (dlang-tour#36)

* Add basics/templates.md (dlang-tour#38)

* Add basics/delgates.md (dlang-tour#40)

* Add basics/interfaces.md (dlang-tour#35)

* Add basics/ranges.md  (dlang-tour#33)

* Add basics/exceptions.md (dlang-tour#37)

* Add basics/associative-arrays.md (dlang-tour#34)

* Add basics/alias-strings.md (dlang-tour#32)

* Add basics/classes.md (dlang-tour#39)

* Create template-meta-programming.md

* Update classes.md (dlang-tour#44)

* Update index.yml

enable all files in basics

* Create template-meta-programming.md

* Create template-meta-programming.md

* Create template-meta-programming.md

* Create template-meta-programming.md

* Create template-meta-programming.md

* Create template-meta-programming.md
  • Loading branch information
SMietzner authored Sep 13, 2017
1 parent a9c0aeb commit 9415c47
Showing 1 changed file with 168 additions and 0 deletions.
168 changes: 168 additions & 0 deletions gems/template-meta-programming.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
# Template-Metaprogrammierung

Wenn du jemals mit *Template-Metaprogrammierung* in C++
in Berührung gekommen bist, wirst du mit Erleichterung
lesen, dass D einige Werkzeuge bereitstellt, um dir das Leben
leichter zu machen.
Metaprogrammierung ist eine Technik, die Entscheidungen
abhängig von Template-Typeigenschaften ermöglicht und so noch
flexiblere Gestaltungsmöglichkeiten für generische Typen bietet.

### `static if` & `is`

`static if` erlaubt die bedingte Kompilierung eines
Code-Blocks. Im Gegensatz zu `if` wird die Bedingung
zur Kompilierzeit ausgewertet:

static if(is(T == int))
writeln("T ist ein int");
static if (is(typeof(x) : int))
writeln("Variable x konvertiert implizit zu int");

Der [`is`-Ausdruck](http://wiki.dlang.org/Is_expression) ist
ein generischer Helfer, der Bedingungen zur Kompilierzeit
auswertet:

static if(is(T == int)) { // T ist Templateparameter
int x = 10;
}

Wenn die Bedingung erfüllt ist, wird der Inhalt des Blocks
kopiert. Die umschließenden Klammern werden weggelassen
und kein weiterer Scope erstellt.
Ein neuer Block / Scope kann allerdings explizit mit `{ {` und `} }`
erzeugt werden.

`static if` kann überall im Code genutzt werden - in
Funktionen, im globalen Scope sowie in Typdefinitionen.

### `mixin template`

Überall, wo Textbausteine gefragt sind, können
`mixin template`s genutzt werden:

mixin template Foo(T) {
T foo;
}
...
mixin Foo!int; // int foo ab hier verfügbar.

`mixin template` können eine beliebige Anzahl an komplexen
Ausdrücken enthalten und werden am Instanziierungspunkt
eingesetzt.
Dies macht einen Präprozessor, wie ihn z.B. C und C++
besitzen, überfüssig.

### Template-Beschränkungen

Ein Template kann mit beliebig vielen Beschränkungen
(engl.: contraints) definiert werden, um so Eigenschaften
eines Typs erzwingen:

void foo(T)(T value)
if (is(T : int)) { // foo!T nur gültig wenn T
// zu int konvertiert
}

Beschränkungen können in booleschen Ausdrücken kombiniert
werden und sogar Funktionsaufrufe enthalten, sofern diese
zur Kompilierzeit ausgwwertet werden können.
Z.B. prüft `std.range.primitives.isRandomAccessRange`,
ob ein Typ eine Range ist, die den `[]`-Operator unterst

### Weiterführende Quellen

### Grundlegende Verweise

- [Tutorial zum Thema D-Templates](https://github.com/PhilippeSigaud/D-templates-tutorial)
- [Bedingte Kompilierung](http://ddili.org/ders/d.en/cond_comp.html)
- [std.traits](https://dlang.org/phobos/std_traits.html)
- [Weiteres zu Templates in _Programming in D_](http://ddili.org/ders/d.en/templates_more.html)
- [Mixins in _Programming in D_](http://ddili.org/ders/d.en/mixin.html)

### Fortgeschrittene Verweise

- [Bedingte Kompilierung](https://dlang.org/spec/version.html)
- [Traits](https://dlang.org/spec/traits.html)
- [Mixin Templates](https://dlang.org/spec/template-mixin.html)
- [Spezifikation: D-Templates](https://dlang.org/spec/template.html)

## {SourceCode}

```d
import std.traits : isFloatingPoint;
import std.uni : toUpper;
import std.string : format;
import std.stdio : writeln;
/*
A Vector, der nur mit Integer- oder
Floatingpoint-Typen arbeitet.
*/
struct Vector3(T)
if (is(T: real))
{
private:
T x,y,z;
/*
Generator für Getter und Setter zur
Vermeidung sich wiederholender
Textbausteine (engl.:boiler plate)!
var -> T getVAR() and void setVAR(T)
*/
mixin template GetterSetter(string var) {
// Nutze mixin zur Erzeugung von
// Funktionsnamen
mixin("T get%s() const { return %s; }"
.format(var.toUpper, var));
mixin("void set%s(T v) { %s = v; }"
.format(var.toUpper, var));
}
/*
Einfache Generierung der Funktionen
getX, setX etc. mit einem Mixin-Template.
*/
mixin GetterSetter!"x";
mixin GetterSetter!"y";
mixin GetterSetter!"z";
public:
/*
Die dot-Funktion ist nur für
Floatingpoint-Typen verfügbar.
*/
static if (isFloatingPoint!T) {
T dot(Vector3!T rhs) {
return x * rhs.x + y * rhs.y +
z * rhs.z;
}
}
}
void main()
{
auto vec = Vector3!double(3,3,3);
// Folgendes funktioniert aufgrund der
// Template-Beschränkung nicht!
// Vector3!string illegal;
auto vec2 = Vector3!double(4,4,4);
writeln("vec dot vec2 = ", vec.dot(vec2));
auto vecInt = Vector3!int(1,2,3);
// besitzt die Function dot nicht, da diese
// statisch nur für Floatingpoint-Typen
// definiert wurde
// vecInt.dot(Vector3!int(0,0,0));
// generierte Getter und Setters!
vecInt.setX(3);
vecInt.setZ(1);
writeln(vecInt.getX, ",",
vecInt.getY, ",", vecInt.getZ);
}
```

0 comments on commit 9415c47

Please sign in to comment.