没有办法做这样的事情,在 C++ 中有吗?
union {
{
Scalar x, y;
}
Scalar v[2];
};
哪里x == v[0]
和y == v[1]
?
既然您使用的是 C++ 而不是 C,而且它们属于相同类型,为什么不直接将 xa 引用到 v[0] 并将 ya 引用到 v[1]
怎么样
union {
struct {
int x;
int y;
};
int v[2];
};
编辑:
union a {
struct b { int first, second; } bee;
int v[2];
};
丑陋,但这样更准确
试试这个:
template<class T>
struct U1
{
U1();
T v[2];
T& x;
T& y;
};
template<class T>
U1<T>::U1()
:x(v[0])
,y(v[1])
{}
int main()
{
U1<int> data;
data.x = 1;
data.y = 2;
}
我以前用过这样的东西。我不确定它是否 100% 符合标准,但对于我需要使用它的任何编译器来说似乎都可以。
struct Vec2
{
float x;
float y;
float& operator[](int i) { return *(&x+i); }
};
如果需要(您可能应该想要),您可以向 operator[] 添加边界检查等,并且您也可以提供 operator[] 的 const 版本。
如果您担心填充(并且不想添加适当的平台特定位来强制取消填充结构),那么您可以使用:
struct Vec2
{
float x;
float y;
float& operator[](int i) {
assert(i>=0);
assert(i<2);
return (i==0)?x:y;
}
const float& operator[](int i) const {
assert(i>=0);
assert(i<2);
return (i==0)?x:y;
}
};
我一直在寻找类似的东西,最终想出了一个解决方案。
我一直在寻找一个数据存储对象,我可以将其用作值数组和单个值(用于最终用户编写 Arduino 库的灵活性)。
这是我想出的:
class data{
float _array[3];
public:
float& X = _array[0];
float& Y = _array[1];
float& Z = _array[2];
float& operator[](int index){
if (index >= 3) return _array[0]; //Make this action whatever you want...
return _array[index];
}
float* operator&(){return _array;}
};
int main(){
data Test_Vector;
Test_Vector[0] = 1.23; Test_Vector[1] = 2.34; Test_Vector[2] = 3.45;
cout<<"Member X = "<<Test_Vector.X;
cout<<"Member Y = "<<Test_Vector.Y;
cout<<"Member Z = "<<Test_Vector.Z;
float* vector_array = &Test_Vector;
cout<<"Array = {"<<vector_array[0]<<", "<<vector_array[1]<<", "<<vector_array[2]<<"}";
}
由于运算符重载,我们可以像使用数组一样使用数据对象,并且可以在函数调用中使用它来传递引用(就像数组一样)!
如果有更多 C++ 经验的人有更好的方法来应用这个最终产品,我很乐意看到它!
编辑:将代码更改为更加跨平台友好
鉴于你的例子:
union
{
struct
{
Scalar x, y;
};
Scalar v[2];
};
正如其他人所指出的,一般来说,该标准不保证 x 和 y 之间没有填充,实际上编译器在结构中插入填充是非常常见的行为。
另一方面,使用以下解决方案:
struct U
{
int v[2];
int& x;
int& y;
};
U::U()
: x(v[0])
, y(v[1])
{}
我不喜欢的主要是我不得不提到 x, y两次。对于我有不止几个元素(比如 10 个)的情况,这变得更不可读并且更难维护 - 例如,如果你想更改 x,y 的顺序,那么你也必须更改下面的索引(当然不是强制性的,但内存中的顺序与字段顺序不匹配,不建议这样做)。此外,U 不能再是POD,因为它需要用户定义的构造函数。最后,x & y 引用会消耗额外的内存。
因此,我提出的(我可以接受的)折衷方案是:
struct Point
{
enum CoordType
{
X,
Y,
COUNT
};
int coords[CoordType::COUNT];
};
typedef Point::CoordType PtCoord;
有了这个,你可以这样做:
Point p;
for ( int i = 0; i < PtCoord::COUNT; i++ )
p.coords[i] = 100;
std::cout << p.coords[PtCoord::X] << " " << p.coords[PtCoord::Y] << std::endl;
// 100 100
有点复杂,但我更喜欢这个而不是参考建议。
根据“标量”是什么,是的,您可以在 C++ 中做到这一点。语法几乎与您在示例中所写的完全一致(甚至可能完全正确,但我对联合感到生疏)。它与 C 相同,除了对可以在联合中的类型有限制(IIRC 它们必须具有默认构造函数)。这是相关的维基百科文章。
使用 C++11,你有匿名联合和结构,它们只是将它们的定义导出到封闭范围,所以你可以这样做:
typedef int Scalar;
struct Vector
{
union
{
struct
{
Scalar x, y;
};
Scalar v[2];
};
};