我想在D中创建一个像这样的矢量结构:
vec u, v;
vec w = [2,6,8];
v.x = 9; // Sets x
v[1] = w.y; // Sets y
u = v; // Should copy data
后来我也想添加u = v * u
等内容。但上面的内容现在也可以
这是我走了多远:
struct vec3f
{
float[3] data;
alias data this;
@property
{
float x(float f) { return data[0] = f; }
float y(float f) { return data[1] = f; }
float z(float f) { return data[2] = f; }
float x() { return data[0]; }
float y() { return data[1]; }
float z() { return data[2]; }
}
void opAssign(float[3] v)
{
data[0] = v[0];
data[1] = v[1];
data[2] = v[2];
}
}
现在这几乎让它像我想要的那样工作,但我觉得这是不是“对”。 opAssign()是否应该返回一些值?
我也想知道这是否真的如此快?我是否尝试添加alias data[0] x;
等,但这不起作用。有任何想法吗?或者这是“它是如何完成的”?也许编译器足够聪明,可以找出或多或少有别名的功能?
答案 0 :(得分:5)
总的来说,这看起来很合理。为了进行分配链接,opAssign可以说可以返回v。但是,在实践中,这经常被忽略,并且可能会导致性能损失(我不知道)。与D1不同,您可以从D2中的函数返回静态数组。
就性能而言,考虑这一点的最佳方式是在装配层面。假设启用了内联,x()
几乎肯定会被内联。静态数组直接存储在结构中,没有额外的间接层。指令return data[0];
将使编译器生成代码以从结构的开头读取偏移量。该偏移量将在编译时得知。因此,最有可能调用x()
将生成完全相同的汇编指令,就像x
实际上是公共成员变量一样。
另一种可能性是使用匿名联合和结构:
struct vec3f
{
union {
float[3] vec;
struct {
float x;
float y;
float z;
}
}
alias vec this; // For assignment of a float[3].
}
请注意,尽管alias this
现在还有很多错误,除非您愿意提交一些错误报告,否则您可能不应该使用它。
答案 1 :(得分:2)
您可以使用opDispatch进行任意深度的调配。我还建议在大小和类型上模板化矢量结构。这是我的比较版本:tools.vector(D1,所以调整有点麻烦)。
答案 2 :(得分:2)
您可以使用数组操作在opAssign中一次性复制整个数组:
data[] = v[];
答案 3 :(得分:1)
@property
{
float x(float f) { return data[0] = f; }
float y(float f) { return data[1] = f; }
float z(float f) { return data[2] = f; }
float x() { return data[0]; }
float y() { return data[1]; }
float z() { return data[2]; }
}
为什么属性?
我建议删除这些行并生成x,y和z公共字段。 这也将提高非内联模式的性能。无论如何,你可以使用union来获得数据[3]数组。