2011-10-19 37 views
19

有一段時間我對D的運算符重載的方向感到困惑,但現在我意識到這是一個美麗的系統......如果它只適用於核心類型(int,float等)。考慮如下代碼:D中優雅的運算符重載

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

這很好,只有我更願意將所有內容都保存在「內部」。有沒有辦法讓這項工作沒有模板的幫助?我知道我在這裏很挑剔,看到沒有性能損失,並且在我需要這樣做的情況下導入模塊並不困難。我只是想知道它是否內置,我忽略了一些東西。

+0

注意'靜態if'不繼續以下後''else' if's。你必須重複'靜態'。 – Bolpat

回答

21

幾乎在所有d重載運算符被定義模板。請注意0​​有一個模板參數,它是一個字符串。所以,不,你不能將它重載爲非模板函數。現在,你不需要第二個模板來完成它(所以如果通過詢問你是否需要模板,你的意思是一個輔助模板,那麼答案是否定的),但重載的運算符函數已經是一個模板。

的規範的方式做你,你想在這裏做的是使用字符串混入:

void opOpAssign(string op)(Vector vector) 
{ 
    mixin("X" ~ op ~ "=vector.X;"); 
    mixin("Y" ~ op ~ "=vector.Y;"); 
} 
+0

該死的速度!謝謝! –

13

這意味着與混入組合

void opOpAssign(string op)(Vector vector) { 
    mixin("X"~op~"=vector.X;"); 
    mixin("Y"~op~"=vector.Y;"); 
} 

何況這可以容易地耦合到其他的算術運算

Vector opBinary(string op)(Vector l)if(op=="+"||op=="-"){//only addition and subtraction makes sense for 2D vectors 
    mixin("return Vector(x"~op~"l.x,y"~op~"l.y;"); 
} 

///take in anything as long as a corresponding binaryOp exists 
///this essentially rewrites all "vec op= variable;" to "vec = vec op variable;" 
void opOpAssign(string op,T)(T l){ 
    this = this.binaryOp!op(l); 
} 

,甚至其它縮放矢量

Vector opBinary(string op)(real l)if(op=="*"||op=="/"){ 
    mixin("return Vector(x"~op~"l,y"~op~"l;"); 
} 

Vector opBinaryRight(string op)(real l)if(op=="*"){// for 2 * vec 
    return this*l; 
} 

請注意,定義的opBinary限制可以傳遞給opOpAssign但你可以去兩種方式(在opOpAssign來定義opBinary

+0

Johnathan首先發布並解釋了更多內容,所以我將其標記爲答案,但我想感謝您的回覆如此之快! –

+0

@FiL檢查我的編輯有點超載善良 –