構造体およびクラスを使用したforeach
- ステップサイズは、
begin
およびend
とともに格納する必要があり、要素の値は、そのステップサイズだけ増加させる必要がある。struct NumberRange {
 int begin;
 int end;
 int stepSize;

 int opApply(int delegate(ref int) dg) const {
 int result;

 for (int number = begin; number != end; number += stepSize) {
 result = dg(number);

 if (result) {
 break;
 }
 }

 return result;
 }
}

import std.stdio;

void main() {
 foreach (element; NumberRange(0, 10, 2)) {
 write(element, ' ');
 }
}
-
import std.stdio;
import std.string;

class Student {
 string name;
 int id;

 this(string name, int id) {
 this.name = name;
 this.id = id;
 }

 override string toString() {
 return format("%s(%s)", name, id);
 }
}

class Teacher {
 string name;
 string subject;

 this(string name, string subject) {
 this.name = name;
 this.subject = subject;
 }

 override string toString() {
 return format("%s teacher %s", subject, name);
 }
}

class School {
private:

 Student[] students;
 Teacher[] teachers;

public:

 this(Student[] students, Teacher[] teachers) {
 this.students = students;
 this.teachers = teachers;
 }

 /* このopApplyのオーバーライドは、foreach変数が
 * Studentの場合に呼び出される。 */
 int opApply(int delegate(ref Student) dg) {
 int result;

 foreach (student; students) {
 result = dg(student);

 if (result) {
 break;
 }
 }

 return result;
 }

 /* 同様に、このopApplyは、foreach変数が
 * Teacherの場合に呼び出される。 */
 int opApply(int delegate(ref Teacher) dg) {
 int result;

 foreach (teacher; teachers) {
 result = dg(teacher);

 if (result) {
 break;
 }
 }

 return result;
 }
}

void printIndented(T)(T value) {
 writeln(" ", value);
}

void main() {
 auto school = new School(
 [ new Student("Can", 1),
 new Student("Canan", 10),
 new Student("Cem", 42),
 new Student("Cemile", 100) ],

 [ new Teacher("Nazmiye", "Math"),
 new Teacher("Makbule", "Literature") ]);

 writeln("Student loop");
 foreach (Student student; school) {
 printIndented(student);
 }

 writeln("Teacher loop");
 foreach (Teacher teacher; school) {
 printIndented(teacher);
 }
}
出力:
生徒ループ Can(1) Canan(10) Cem(42) Cemile(100) 教師のループ 数学教師 Nazmiye 文学教師 Makbule
ご覧のとおり、
opApply()
の2つのオーバーライドの実装は、反復処理の対象となるスライスを除いてまったく同じである。コードの重複を減らすために、共通の機能を実装関数テンプレートに移動し、2つのopApply()
オーバーライドから呼び出すようにすることができる。class School {
// ...

 int opApplyImpl(T)(T[] slice, int delegate(ref T) dg) {
 int result;

 foreach (element; slice) {
 result = dg(element);

 if (result) {
 break;
 }
 }

 return result;
 }

 int opApply(int delegate(ref Student) dg) {
 return opApplyImpl(students, dg);
 }

 int opApply(int delegate(ref Teacher) dg) {
 return opApplyImpl(teachers, dg);
 }
}