我正在为数学库创建自己的向量结构。
目前,我会创建类似于这样的结构:
template <unsigned int size, typename T>
struct vector {
// array of elements
T elements[size];
// ...
};
Run Code Online (Sandbox Code Playgroud)
然而,数学库的主要用例将导致主要使用 2 维、3 维和 4 维向量(通常为vec2、vec3和vec4)。因此,一个有用的功能是能够在可能的情况下从向量访问 x、y、z 和 w 值。然而,这也存在一些问题。
、x、和成员需要是、等的引用变量。这意味着,如果向量的元素少于 4 个,则某些引用将不会被初始化y。zwelements[0]elements[1]
当然,这可以通过专门的模板来实现,这就是我目前正在做的:
template <unsigned int size, typename T>
struct vector {
// ...
}
template <typename T>
struct vector<2, T> {
// same as with before, except with references to X and Y elements.
// these are successfully initialised in the constructor because the vector is guaranteed to have 2 elements
T &x;
T &y;
// ...
}
// and so on for 3D and 4D vectors
Run Code Online (Sandbox Code Playgroud)
这可行,但远不方便。在实践中,vector结构体很大并且有很多函数和运算符重载。当它专门化为其他大小时,这些函数和运算符重载需要从通用结构体复制粘贴到2D、3D和4D结构体,这是非常低效的。请记住:我在专业化之间唯一改变的是参考变量!所有其他成员都完全相同,因此我宁愿重用他们的代码。
另一种解决方案是从一个基类继承。我不完全确定如何以允许继承的运算符重载返回子向量结构中的值而不是父结构中的值的方式执行此操作。
所以,我的问题是:如何有效地重用专用模板结构中的代码,同时仍然能够(在本例中)拥有x、y、z和w引用(如果可用)?
cig*_*ien 10
如果您愿意通过函数访问成员来稍微更改界面,即
vector<2, int> v;
v.x() = 5; // instead of v.x = 5;
Run Code Online (Sandbox Code Playgroud)
那么您可以在没有任何专业化的情况下完成此操作,并完全回避代码重用的问题。
在类模板中,只需为每个索引添加尽可能多的成员函数,并断言访问有效:
template <unsigned int size, typename T>
struct vector {
T elements[size];
// ...
T& x() {
static_assert(size > 0);
return elements[0];
}
T& y() {
static_assert(size > 1);
return elements[1];
}
// ... and so on
};
Run Code Online (Sandbox Code Playgroud)
现在,这将在访问适当的元素时起作用,否则会给出错误。
vector<1, int> v1;
vector<2, int> v2;
v1.x() = 5; // ok
v1.y() = 4; // error, v1 can only access x
v2.y() = 3; // ok, v2 is big enough
Run Code Online (Sandbox Code Playgroud)
这是一个演示。
您可以为成员函数static_assert编写约束,而不是requires
T& x() requires (size > 0) {
return elements[0];
}
// etc ...
Run Code Online (Sandbox Code Playgroud)
这是一个演示。
| 归档时间: |
|
| 查看次数: |
260 次 |
| 最近记录: |