Некоторое время я смущался о направлении перегрузки оператора D, но теперь я понимаю, что это красивая система... если она будет работать только с основными типами (int, float и т.д.). Рассмотрим следующий код:
struct Vector {
float X, Y;
void opOpAssign(string op)(Vector vector) {
X.opOpAssign!op(vector.X); // ERROR: no property "opOpAssign" for float
Y.opOpAssign!op(vector.Y); // ERROR: ditto
}
}
Это был бы красивый код, если бы он работал, поскольку он перегружает все операторы + =, - =, * = и т.д. одним способом. Однако, как вы можете видеть, это не работает из коробки. Я создал решение с использованием шаблонов (бог, я люблю D):
template Op(string op, T) {
void Assign(ref T a, T b) {
static if (op == "+") a += b;
else if (op == "-") a -= b;
else if (op == "*") a *= b;
else if (op == "/") a /= b;
}
}
struct Vector {
float X, Y;
void opOpAssign(string op)(Vector vector) {
Op!(op, typeof(X)).Assign(X, vector.X);
Op!(op, typeof(Y)).Assign(Y, vector.Y);
}
}
Это прекрасно, только я бы предпочел сохранить все "в доме". Есть ли способ сделать эту работу без помощи шаблона? Я знаю, что я здесь придирчив, потому что нет потери производительности, и мне не сложно импортировать модуль в ситуации, когда мне нужно это делать. Мне просто интересно, встроена ли она, и я что-то пропускаю.