Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ &引用;“追溯性结合”能做到吗?_C++_Templates_Unions - Fatal编程技术网

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;istd::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...