Consider the following structure:
struct vec4
{
union{float x; float r; float s};
union{float y; float g; float t};
union{float z; float b; float p};
union{float w; float a; float q};
};
Something like this seems to be used in e.g. GLM to provide GLSL-like types like vec4
, vec2
etc..
But although the intended usage is like to make this possible
vec4 a(1,2,4,7);
a.x=7;
a.b=a.r;
, it seems to be an undefined behavior, because, as quoted here,
In a union, at most one of the data members can be active at any time, that is, the value of at most one of the data members can be stored in a union at any time.
Wouldn't it be better to e.g. use just define the structure something like the following?
struct vec4
{
float x,y,z,w;
float &r,&g,&b,&a;
float &s,&t,&p,&q;
vec4(float X,float Y,float Z,float W)
:x(X),y(Y),z(Z),w(W),
r(x),g(y),b(z),a(w),
s(x),t(y),p(z),q(w)
{}
vec4()
:r(x),g(y),b(z),a(w),
s(x),t(y),p(z),q(w)
{}
vec4(const vec4& rhs)
:x(rhs.x),y(rhs.y),z(rhs.z),w(rhs.w),
r(x),g(y),b(z),a(w),
s(x),t(y),p(z),q(w)
{}
vec4& operator=(const vec4& rhs)
{
x=rhs.x;
y=rhs.y;
z=rhs.z;
w=rhs.w;
return *this;
}
};
Or am I working around a non-existent issue? Is there maybe some special statement allowing access to identically-typed inactive union members?
I think the quote in which you are referring to is directed at having different types with in the union.
These are different data, conveniently stored into the same structure, unions are not supposed to be a casting mechanism.
GLM approach uses the same data and uses the union for an alias mechanic.
Your approach might be 'better' C++ but its worse 'Engineering'. Vector math needs to be fast, and the smaller the better in this case.
Your implementation is makes the vector 3 times bigger.
sizeof(glm::vec4); // 16
whilesizeof(your_vec4); // 48 - ouch
If you where processing a large armount of these which is often the case, 3 times as more cache misses withyour_vec4
.I think you are right though glm's use of unions as alias's is a bit much, while I'm not sure if its undefined, but this type of thing I've seen a lot without much issue, and glm is widely used.
I don't really see the need to emulate glsl in C++, and
struct { float x,y,z,w; }
would be better (at least in my mind).