Elegante sobrecarga del operador en D

Durante un tiempo estaba confundido acerca de la dirección de la sobrecarga del operador de D, pero ahora me doy cuenta de que es un sistema hermoso ... si solo funcionara con tipos de núcleo (int, float, etc.). Considere el siguiente código:

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
    }
}

Este sería un código hermoso si funcionara, ya que sobrecarga todos los operadores + =, - =, * =, etc. en un método. Sin embargo, como puede ver, no funciona fuera de la caja. He creado una solución usando plantillas (dios amo 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);
    }
}

Esto está bien, solo que preferiría mantener todo "en casa". ¿Hay alguna manera de hacer que esto funcione sin la ayuda de una plantilla? Sé que soy exigente aquí, ya que no hay pérdida de rendimiento y no es difícil importar un módulo en una situación en la que necesito hacer esto. Me pregunto si está integrado y estoy pasando por alto algo.

Respuestas a la pregunta(2)

Su respuesta a la pregunta