C++并集中的命名结构

Named Structures in C++ Unions

本文关键字:结构 集中 C++      更新时间:2023-10-16

在C++中,我试图创建一个专门的点类作为并集,如下所示:

union point
{
  struct { float x, y, z; };
  float val[3];
  float operator[](unsigned i) { return val[i]; }
};

为了可读性,我可以将该点作为数组或多个点进行访问。

然而,让我们说,我想概括一下:

template<unsigned n>
  union point
  {
    struct { float ???; };
    float val[n];
    float operator[](unsigned i) { return val[i]; }
  };

我可以为???输入什么?根据n是什么,我可以有xx, yx, y, zx, y, z, w。解决方案?转发声明!

template<unsigned n>
  union point
  {
    struct coords;
    float val[n];
    float operator[](unsigned i) { return val[i]; }
  };
template<>
  struct point::coords<3>
  {
    float x, y, z;
  };
// ...

但这似乎并不奏效。然而,在GCC 4.6下,每当我尝试使用成员时,它都会编译,比如:

point<3> val;
val.x;

我得到错误:

error: ‘union point<3>’ has no member named ‘x’

即使我将val.x更改为val.coords::x,我仍然会得到错误:

error: ‘union point<3>::coords’ is not a base of ‘union point<3>’

在联合定义中添加using coords;也没有帮助。

根据GCC 4.6,是否有任何方法可以实现这一点?有不同的方法吗?这可能吗?

我建议使用可变宏来定义union<N>模板。

template<unsigned int N>
union point; // declared and undefined
#define DECLARE_POINT(NUM, ...) 
template<> 
union point<NUM> 
{ 
  struct { float __VA_ARGS__; }; 
  float val[NUM]; 
}
#undef DECLARE_POINT

完成此操作后,您可以简单地声明/定义坐标的各种组合(在本例中为#undef之前):

DECLARE_POINT(1, x);
DECLARE_POINT(2, x, y);
DECLARE_POINT(3, x, y, z);

相当于

template<> union point<1> { struct { float x; }; float val[1]; };
template<> union point<2> { struct { float x, y; }; float val[2]; };
template<> union point<3> { struct { float x, y, z; }; float val[3]; };

它可以按照你要求的方式使用:

point<3> p;
p.z = 0;

此外,您可以使用一些模板技巧(static_assert)进行交叉检查,以检查数量参数(例如1,2,3,...)与传递的总参数(例如,x,y,z,...)是否匹配。

工会内部的这一行:

struct coords;

forward声明了类型coords,但在模板化的并集中没有struct coords字段。

此外,只有匿名结构的成员才能作为联合的顶级字段访问。例如:

union foo {
    struct { // anonymous struct
        short i;
        short j;
    };
    int k;
};
foo f;
// it's possible to access the fields of the anonymous struct as if they were
// direct members of the union
f.i = 4;
f.j = 8;
std::cout << f.k;

如果你只专门化内部的struct类型,我不确定你是否能够做到这一点。

然而,这是有效的:

template<unsigned n>
union point;
template<>
union point<2> {
    struct { float x, y; };
    float val[2];
};
template<>
union point<3> {
    struct { float x, y, z; };
    float val[3];
};

但也有许多不利因素;主要的一点是,您必须为CCD_ 19的每个版本重新定义CCD_。

我知道如何使用模板,但我不是模板之神,所以存在一个聪明的技巧并不是毫无疑问的。