D 中的优雅运算符重载
有一段时间我对 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);
}
}
这很好,只是我更喜欢将所有内容保留在“内部”。有没有一种方法可以在不借助模板的情况下完成这项工作?我知道我在这里很挑剔,因为没有性能损失,而且在我需要这样做的情况下导入模块并不难。我只是想知道它是否是内置的,而我忽略了一些东西。
For a while I was confused about the direction of D's operator overloading, but now I realize it's a beautiful system... if It would only work with core types (int, float, etc). Consider the follow code:
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
}
}
This would be beautiful code if it worked, seeing as it overloads all +=, -=, *=, etc.. operators in one method. However, as you can see, it doesn't work out of the box. I have created a solution using templates (god I love 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);
}
}
This is fine, only I'd much prefer to keep everything "in house". Is there a way to make this work without the aid of a template? I know I'm being picky here, seeing as there's no performance loss and it's not hard to import a module in situation I need to do this. I'm just wondering if it's built in and I'm overlooking something.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
根据定义,D 中几乎所有重载运算符都是模板。请注意,
void opOpAssign(string op)(Vector vector)
有一个模板参数,它是一个字符串。所以,不,你不能将它重载为非模板函数。现在,您不需要第二个模板来执行此操作(因此,如果通过询问您是否需要模板,您的意思是辅助模板,那么答案是否定的),但重载的运算符函数已经是一个模板。执行此操作的规范方法是使用字符串混合:
Almost all overloaded operators in D are templates by definition. Notice that
void opOpAssign(string op)(Vector vector)
has a template parameter which is a string. So, no you can't overload it as a non-template function. Now, you don't need a second template to do it (so if by asking whether you need a template, you mean a helper template, then the answer is no), but the overloaded operator function is already a template.The canonical way to do what you you're trying to do here is to use string mixins:
这意味着与 mixin 结合使用,
更不用说它可以轻松地与其他算术运算
甚至其他缩放 Vector
相结合,请注意,定义的 opBinary 限制了可以传递给 opOpAssign 的内容 但你可以采用两种方式(根据
opOpAssign
定义opBinary
)this is meant to be combined with mixins
not to mention this can easily be coupled to other arithmetic operations
and even to other scaling the Vector
note that the defined
opBinary
s restrict what can be passed toopOpAssign
but you can go both ways (defineopBinary
in terms ofopOpAssign
)