D 隐式转换 Vector(T) 类型
比较代码片段 A:
struct Vector2(T) {
// ...
auto opCast(U)() {
return U(x, y);
}
void opOpAssign(string op)(Vector2 vector) {
mixin ("x" ~ op ~ "= vector.x;");
mixin ("y" ~ op ~ "= vector.y;");
}
}
void main() {
auto fVec = Vector2!float(1.5, 1.5);
auto dVec = Vector2!double(1.5, 1.5);
// Benchmark: Loop following 10 million times.
fVec += cast(Vector2!float) dVec;
dVec -= cast(Vector2!double) fVec;
}
和 B:
struct Vector2(T) {
// ...
void opOpAssign(string op, U)(Vector2!U vector) {
mixin ("x" ~ op ~ "= vector.x;");
mixin ("y" ~ op ~ "= vector.y;");
}
}
void main() {
auto fVec = Vector2!float(1.5, 1.5);
auto dVec = Vector2!double(1.5, 1.5);
// Benchmark: Same as A.
fVec += dVec;
dVec -= fVec;
}
在我的基准测试(DMD、Win7)中,A 比 B 快约 50 毫秒。为什么会这样?如果 A 更快,我想使用它,但无论我如何尝试,我都无法让 Vector2!double 隐式转换为 Vector2!float。关于如何隐式转换这些类型有什么想法吗?或者是否有一些争论为什么我不应该隐式地投射它们?
我正在设置 GDC 和 LDC 来使用这些编译器执行此基准测试,但有人立即知道这是否只是 DMD 优化问题?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
就编译器而言,同一模板的两个不同实例没有什么共同点,只不过是两个完全独立的类型。您可以声明
而不是模板化
Vector2
,这没有什么区别。Vector2!float
和Vector!double
是完全不同的类型。对于您声明的任何类型,如果您想要在它们之间进行转换的方法,则必须声明它们 - 无论是opCast
、alias this
、构造函数,或其他什么。我相信,要实现隐式转换的唯一方法是使用alias this
,尽管使用 棘轮狂人指出,在浮点数和双精度数之间隐式转换不是 D 通常的工作方式,并且可以说是一个坏主意。至于为什么A比B快,我不知道。我实际上预计情况会是相反的。但根据编译器到底在做什么,它可能会在以后发生变化,并且它很容易因编译器的不同而有所不同。由于您在 1000 万 次迭代中只看到了 50 毫秒的差异,因此我会选择从 API 角度来看更有意义的版本(无论您认为是哪一个)。不过,我反对使用第一个,只是因为我认为在 float 和 double 之间隐式转换不是一个好主意,但这取决于您,因为这是您的代码。
顺便说一句,如果您愿意,您可以使用 std.conv.to 而不是直接调用
opCast
。这样就不太容易出错,因为如果你搞砸了 opCast 的定义,它会大喊大叫,而编译器更可能无论如何都会这样做,因为强制转换是一种非常生硬的工具。Two different instantiations of the same template have nothing more in common than two completely separate types as far as the compiler is concerned. You could declare
instead of templatizing
Vector2
, and it would make no difference.Vector2!float
andVector!double
are completely different types. And with any types that you declare, if you want ways to convert between them, you're going to have to declare them - be theyopCast
,alias this
, constructors, or whatever. I believe that the only way that you're ever going to get implicit conversion to work is withalias this
, though as ratchet freak points out, implicitly converting between floats and doubles is not how D normally works and is arguably a bad idea.As to why A is faster than B, I don't know. I would have actually expected it to be the other way around. But depending on what exactly the compiler is doing, it could change later, and it could easily vary from compiler to compiler. And since you're only seeing a 50ms difference over 10 million iterations, I'd go with the version that makes more sense from an API perspective (whichever you think that is). I'd argue going with the first one though, simply because I don't think that it's a good idea to implicitly convert between float and double, but that's up to you, since it's your code.
By the way, you can use std.conv.to instead of calling
opCast
directly if you want. It's less error-prone that way, since then it'll yell if you screw up definingopCast
, whereas the compiler is more likely to just do it anyway, since cast is very much a blunt instrument.您不应该将
double
隐式转换为 single 精度浮点,就像您不能从long
隐式转换一样code> 到int
因为你会失去精度。大多数语言都要求您在转换时明确何时要丢失精度。最好遵循该语言中现有的约定,而不是强制执行自己的约定。
You shouldn't implicitly cast
double
to single precisionfloat
ing point, just like you can't implicitly convert fromlong
toint
because you'll lose precision.Most languages require you to make it clear when you want to lose precision when converting. and it is best if you follow the existing conventions in the language instead of enforcing your own.