opDispatch & opApply

Мова D дозволяє перевизначати такі оператори, як +, - або оператори виклику () для класів та структур. Ми трохи ближче познайомимось з двома спеціальними операторами для перевантаження opDispatch і opApply.

opDispatch

opDispatch може бути визначений як функція-член структури чи класу. Будь-який виклик до невизначеної функції-члену до цього типу передається до opDispatch разом із ім'ям такої невідомої функції, як параметр шаблону string. opDispatch є всеперехоплюючою функцією, яка забезпечує ще один рівень загального програмування, який повністю розраховується під час компіляції!

struct C {
    void callA(int i, int j) { ... }
    void callB(string s) { ... }
}
struct CallLogger(C) {
    C content;
    void opDispatch(string name, T...)(T vals) {
        writeln("called ", name);
        mixin("content." ~ name)(vals);
    }
}
CallLogger!C l;
l.callA(1, 2);
l.callB("ABC");

opApply

Альтернативний спосіб реалізації циклу foreach окрім визначеного користувачем діапазону, є реалізація opApply. Виконання ітерації з foreach для такого типу викликатиме перенавантажений оператор opApply зі спеціальним делегатом, як параметр:

class Tree {
    Tree lhs;
    Tree rhs;
    int opApply(int delegate(Tree) dg) {
        if (lhs && lhs.opApply(dg)) return 1;
        if (dg(this)) return 1;
        if (rhs && rhs.opApply(dg)) return 1;
        return 0;
    }
}
Tree tree = new Tree;
foreach(node; tree) {
    ...
}

Компілятор трансформує тіло foreach у спеціального делегата, який передаватиметься об'єкту. Його один і єдиний параметр міститиме поточне значення ітерації. Магічне повернення значення int повинно бути інтерпретовано і якщо воно не дорівнює 0, ітерацію потрібно зупинити.

Поглиблення

rdmd playground.d