2011-10-19 96 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检查我的编辑有点超载善良 –