ポインタ
- パラメータが
int
のような値型の場合、引数は関数にコピーされる。参照パラメータを定義する推奨方法は、ref
として指定することだ。別の方法は、パラメーターを実際の変数を指すポインタとして定義することだ。プログラムの変更部分はハイライト表示されている:
void swap(int * lhs, int * rhs) {
 int temp = *lhs;
 *lhs = *rhs;
 *rhs = temp;
}

void main() {
 int i = 1;
 int j = 2;

 swap(&i, &j);

 assert(i == 2);
 assert(j == 1);
}
プログラムの末尾のチェックは現在、パスする。
Node
およびList
は、int
型でのみ動作するように記述されている。これらの型は、名前の後に(T)
を追加し、定義内の適切なint
をT
に置き換えることで、構造体テンプレートに変換することができる。struct Node(T) {
 T element;
 Node * next;

 string toString() const {
 string result = to!string(element);

 if (next) {
 result ~= " -> " ~ to!string(*next);
 }

 return result;
 }
}

struct List(T) {
 Node!T * head;

 void insertAtHead(T element) {
 head = new Node!T(element, head);
 }

 string toString() const {
 return format("(%s)", head ? to!string(*head) : "");
 }
}
List
は、あらゆる型で使用できるようになった。import std.stdio;
import std.conv;
import std.string;

// ...

struct Point {
 double x;
 double y;

 string toString() const {
 return format("(%s,%s)", x, y);
 }
}

void main() {
 List!Point points;

 points.insertAtHead(Point(1.1, 2.2));
 points.insertAtHead(Point(3.3, 4.4));
 points.insertAtHead(Point(5.5, 6.6));

 writeln(points);
}
出力:
((5.5,6.6) -> (3.3,4.4) -> (1.1,2.2))
- この場合、リストの最後のノードを指す別のポインタが必要になる。新しい変数を管理するため、新しいコードは必然的に複雑になる:
struct List(T) {
 Node!T * head;
 Node!T * tail;

 void append(T element) {
 /* 最後のノードの後にノードがないため、
 * 新しいノードのnextポインタを'null'に設定する。 */
 auto newNode = new Node!T(element, null);

 if (!head) {
 /* リストは空になった。新しいノードが
 * 先頭になる。 */
 head = newNode;
 }

 if (tail) {
 /* このノードを現在の末尾の後に配置する。 */
 tail.next = newNode;
 }

 /* 新しいノードが新しい末尾になる。 */
 tail = newNode;
 }

 void insertAtHead(T element) {
 auto newNode = new Node!T(element, head);

 /* 新しいノードが先頭ノードになる。 */
 head = newNode;

 if (!tail) {
 /* リストは空になった。新しいノードが
 * 末尾になる。 */
 tail = newNode;
 }
 }

 string toString() const {
 return format("(%s)", head ? to!string(*head) : "");
 }
}
insertAtHead()
の新しい実装は、実際にはもっと短くすることができる。void insertAtHead(T element) {
 head = new Node!T(element, head);

 if (!tail) {
 tail = head;
 }
}
次のプログラムは、新しい
List
を使用して、奇数の値を持つPoint
オブジェクトを先頭に、偶数の値を持つPoint
オブジェクトを最後に挿入する。void main() {
 List!Point points;

 foreach (i; 1 .. 7) {
 if (i % 2) {
 points.insertAtHead(Point(i, i));

 } else {
 points.append(Point(i, i));
 }
 }

 writeln(points);
}
出力:
((5,5) -> (3,3) -> (1,1) -> (2,2) -> (4,4) -> (6,6))