C++ &引用;“追溯性结合”能做到吗?
我有两个类:模板类和从中继承的常规类:C++ &引用;“追溯性结合”能做到吗?,c++,templates,unions,C++,Templates,Unions,我有两个类:模板类和从中继承的常规类: template <int N> class Vector { float data[N]; //etc. (math, mostly) }; class Vector3 : public Vector<3> { //Vector3-specific stuff, like the cross product }; 模板类向量 { 浮点数据[N]; //等等(主要是数学) }; 类向量3:公共向量 { /
template <int N> class Vector
{
float data[N];
//etc. (math, mostly)
};
class Vector3 : public Vector<3>
{
//Vector3-specific stuff, like the cross product
};
模板类向量
{
浮点数据[N];
//等等(主要是数学)
};
类向量3:公共向量
{
//向量3特定的东西,比如叉积
};
现在,我希望在子类中有x/y/z成员变量(完整成员,而不仅仅是getter,我还希望能够设置它们)。但为了确保所有(继承的)数学都能解决,x
必须引用与数据[0]
,y
到数据[1]
,等等相同的内存。本质上,我想要一个并集,但我不能在基类中声明一个,因为我不知道此时向量中的浮点数
那么,这能做到吗?是否有某种预处理器/typedef/template魔法可以实现我想要的
PS:如果有帮助的话,我正在使用g++4.6.0和-std=c++0x
Edit:虽然引用会给出我想要的语法,但理想的解决方案不会使类变得更大(引用也确实如此!一个Vector
是12字节。一个Vector3
带引用的是40!)。怎么样:
class Vector3 : public Vector<3>
{
public:
// initialize the references...
Vector3() : x(data[0]), y(data[1]), z(data[2]){}
private:
float& x;
float& y;
float& z;
};
类向量3:公共向量
{
公众:
//初始化引用。。。
向量3():x(数据[0]),y(数据[1]),z(数据[2]){}
私人:
浮动&x;
浮动&y;
浮动&z;
};
当然,如果你想让它们占据相同的空间,那就不同了
使用一点模板魔法,您可以执行以下操作
#include <iostream>
template <int N, typename UnionType = void*> struct Vector
{
union
{
float data[N];
UnionType field;
};
void set(int i, float f)
{
data[i] = f;
}
// in here, now work with data
void print()
{
for(int i = 0; i < N; ++i)
std::cout << i << ":" << data[i] << std::endl;
}
};
// Define a structure of three floats
struct Float3
{
float x;
float y;
float z;
};
struct Vector3 : public Vector<3, Float3>
{
};
int main(void)
{
Vector<2> v1;
v1.set(0, 0.1);
v1.set(1, 0.2);
v1.print();
Vector3 v2;
v2.field.x = 0.2;
v2.field.y = 0.3;
v2.field.z = 0.4;
v2.print();
}
#包括
模板结构向量
{
联盟
{
浮点数据[N];
联合类型字段;
};
无效集(整数i,浮点f)
{
数据[i]=f;
}
//在这里,现在处理数据
作废打印()
{
对于(int i=0;i std::cout这里有一种可能性,从我的回答中抄袭到:
类向量3:公共向量
{
公众:
浮动&x,&y,&z;
向量3():x(数据[0]),y(数据[1]),z(数据[2]){}
};
这有一些问题,比如要求您定义自己的复制构造函数、赋值运算符等。模板专门化如何
template <int N> class Vector
{
public:
float data[N];
};
template <>
class Vector<1>
{
public:
union {
float data[1];
struct {
float x;
};
};
};
template <>
class Vector<2>
{
public:
union {
float data[2];
struct {
float x, y;
};
};
};
template <>
class Vector<3>
{
public:
union {
float data[3];
struct {
float x, y, z;
};
};
};
class Vector3 : public Vector<3>
{
};
int main() {
Vector3 v3;
v3.x;
v3.data[1];
};
模板类向量
{
公众:
浮点数据[N];
};
模板
类向量
{
公众:
联合{
浮动数据[1];
结构{
浮动x;
};
};
};
模板
类向量
{
公众:
联合{
浮动数据[2];
结构{
浮动x,y;
};
};
};
模板
类向量
{
公众:
联合{
浮动数据[3];
结构{
浮动x,y,z;
};
};
};
类向量3:公共向量
{
};
int main(){
矢量3 v3;
v3.x;
v3.数据[1];
};
编辑好的,这里有一种不同的方法,但它引入了一个额外的标识符
template <int N> class Data
{
public:
float data[N];
};
template <> class Data<3>
{
public:
union {
float data[3];
struct {
float x, y, z;
};
};
};
template <int N> class Vector
{
public:
Data<N> data;
float sum() { }
float average() {}
float mean() {}
};
class Vector3 : public Vector<3>
{
};
int main() {
Vector3 v3;
v3.data.x = 0; // Note the extra "data".
v3.data.y = v3.data.data[0];
};
模板类数据
{
公众:
浮点数据[N];
};
模板类数据
{
公众:
联合{
浮动数据[3];
结构{
浮动x,y,z;
};
};
};
模板类向量
{
公众:
数据;
浮点和(){}
浮点平均值(){}
浮点平均值(){}
};
类向量3:公共向量
{
};
int main(){
矢量3 v3;
v3.data.x=0;//注意额外的“数据”。
v3.data.y=v3.data.data[0];
};
您可以执行以下操作:
template <int N> struct Vector
{
float data[N];
//etc. (math, mostly)
};
struct Vector3_n : Vector<3>
{
//Vector3-specific stuff, like the cross product
};
struct Vector3_a
{
float x, y, z;
};
union Vector3
{
Vector3_n n;
Vector3_a a;
};
模板结构向量
{
浮点数据[N];
//等等(主要是数学)
};
结构向量3\u n:Vector
{
//向量3特定的东西,比如叉积
};
结构向量3_a
{
浮动x,y,z;
};
联合向量3
{
向量3;
矢量3_a;
};
现在:
vector3v;
v、 n.crosswhere();
std::cout我不久前写了一篇文章(也允许getter/setter),但这是一个不可移植的garrish hack,你真的不应该这么做。但是,我想我还是把它扔掉。基本上,它使用一个特殊类型,每个成员的数据为0。然后,该类型的成员函数抓住这个指针,计算父向量3的位置,然后使用t他Vector3
s成员访问数据。这种黑客行为或多或少像一个引用,但不占用额外内存,没有重置问题,我很确定这是未定义的行为,因此可能会导致
类向量3:公共向量
{
公众:
结构xwrap{
运算符float()常量;
浮点&运算符=(浮点b);
浮点运算符=(常量xwrap){}
}x;
结构ywrap{
运算符float()常量;
浮点&运算符=(浮点b);
浮点运算符=(常量ywrap){}
}y;
结构zwrap{
运算符float()常量;
浮点&运算符=(浮点b);
浮点运算符=(常量zwrap){}
}z;
//向量3特定的东西,比如叉积
};
#定义父(成员)\
(*重新解释铸件(尺寸(本)-偏移量(矢量3,构件)))
Vector3::xwrap::运算符float()常量{
返回父项(x)[0];
}
浮点和向量3::xwrap::运算符=(浮点b){
返回父级(x)[0]=b;
}
Vector3::ywrap::运算符float()常量{
返回父项(y)[1];
}
浮点和向量3::ywrap::运算符=(浮点b){
返回父项(y)[1]=b;
}
Vector3::zwrap::运算符float()常量{
返回父项(z)[2];
}
浮点和向量3::zwrap::运算符=(浮点b){
返回父项(z)[2]=b;
}
结束一个老问题:不。这让我很难过,但你做不到
你可以靠近,比如:
Vector3.x() = 42;
或
或
甚至
Vector3.x = 42; //At the expense of almost quadrupling the size of Vector3!
都是触手可及的(见其他答案——它们都很好)。但我的理想是
Vector3.x = 42; //In only 12 bytes...
这是不可行的。如果你想从基类继承你所有的函数就不行了
最后,所讨论的代码最终得到了相当多的调整——它现在是严格意义上的4成员向量(x、y、z、w),使用SSE进行向量数学,并且有多个几何类(点、向量、比例等),因此出于类型正确性的原因,继承核心函数不再是一个选项
希望这能让其他人少受几天的挫折
Vector3.x() = 42;
Vector3.x(42);
Vector3.n.x = 42;
Vector3.x = 42; //At the expense of almost quadrupling the size of Vector3!
Vector3.x = 42; //In only 12 bytes...