允许在D中进行[i]和.xyz操作的快速向量结构?

时间:2010-06-23 00:58:33

标签: struct operator-overloading d

我想在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;等,但这不起作用。有任何想法吗?或者这是“它是如何完成的”?也许编译器足够聪明,可以找出或多或少有别名的功能?

4 个答案:

答案 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]数组。