This question is my mistake.
The code described below is being built well with no problem.
I have this class.
Vector.h
struct Vector
{
union
{
float elements[4];
struct
{
float x;
float y;
float z;
float w;
};
};
float length();
}
Vector.cpp
float Vector::length()
{
return x; // error: 'x' was not declared in this scope
}
How to access the member x,y,z,w?
You need an instance of your struct inside the anonymous union. I don't know exactly what you want to achive, but e.g. something like this would work:
struct Vector
{
union
{
float elements[4];
struct
{
float x, y, z, w;
}aMember;
};
float length() const
{
return aMember.x;
}
};
What you have created is not an anonymous member, but anonymous type (which is useless by itself). You have to create a member of your anonymous type. This concerns both your struct and your union.
Adjust the header like this:
struct Vector
{
union
{
float elements[4];
struct
{
float x;
float y;
float z;
float w;
} v;
} u;
float length();
};
Now you can access your members like this:
u.elements[0] = 0.5f;
if(u.v.x == 0.5f) // this will pass
doStuff();
Related
Before anyone says anything I know this is probably not recommended but I am still curious if there is a better way to do it or reasons not to beyond just it's a strange thing to do.
I started looking into this because I wanted to access elements of an array directly with semantically named members in the class while still being able to iterate over the array and not have to call/create some getter or setter methods.
I have a class definition that looks something like this.
class Vertex{
public:
Vertex(float x,float y,float z,float w);
float v[4];
float &x,&y,&Z,&w;
};
And a constructor that looks like this. My question is. Is there a better way of doing what I am doing in the constructor?
Vertex::Vertex(float vx,float vy,float vz,float vw):
x(*const_cast<float*>( &this->v[0] )),
y(*const_cast<float*>( &this->v[1] )),
z(*const_cast<float*>( &this->v[2] )),
w(*const_cast<float*>( &this->v[3] ))
{
v[0]=vx;
v[1]=vy;
v[2]=vz;
v[3]=vw;
}
EDIT
I'm an idiot... you can just do it like Jonathan Wakely said.
x(v[0])
I guess I had some other problems before when I tried it. Oh well.
Vertex::Vertex(float vx,float vy,float vz,float vw):
v { vx, vy, vz, vw },
x(v[0]),
y(v[1]),
z(v[2]),
w(v[3])
{
}
I'd avoid writing reference members here. The reason is that reference members prevent defaulted (compiler generated) copy/assignment special members.
class Vertex{
public:
Vertex(float x,float y,float z,float w)
: v { x, y, z, w } { }
float &x() { return v[0]; }
float &y() { return v[1]; }
float &z() { return v[2]; }
float &w() { return v[3]; }
float const &x() const { return v[0]; }
float const &y() const { return v[1]; }
float const &z() const { return v[2]; }
float const &w() const { return v[3]; }
private:
float v[4];
};
You could go this way too:
class Vertex
{
public:
float x;
float y;
float z;
float w;
Vertex(float x, float y, float z, float w);
float&
operator[](int i)
{ return *(&x + i); }
float
operator[](int i) const
{ return *(&x + i); }
};
Probably, this variant is better (compared to other alternatives) because it requires less code and gives you the additional ability to iterate over Vertex in array-style.
Personally I like #sehe's answer best but I'll give you an alternative.
struct Vector4 {
float x;
float y;
float z;
float w;
};
union VectorUnion {
Vector4 vector;
float array[4];
};
Then you can just use the VectorUnion inside your Vertex class or on its own...
I am concerned about the fact that this is a C construct and that C++ struct is slightly different (it includes the vtable etc) but I think that it should work.
Again, I think #sehe's answer is better.
In C++, I'm trying to create a specialized point class as a union, like so:
union point
{
struct { float x, y, z; };
float val[3];
float operator[](unsigned i) { return val[i]; }
};
So that I can access the point as an array or as multiple points, for readability.
However, let's say that I want to generalise this a bit:
template<unsigned n>
union point
{
struct { float ???; };
float val[n];
float operator[](unsigned i) { return val[i]; }
};
What can I put for ???? I could have x, x, y, x, y, z, or x, y, z, w depending on what n is. Solution? Forward declarations!
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;
};
// ...
But this doesn't appear to work. Under the GCC 4.6, it compiles, however, whenever that I try to use the members, like so:
point<3> val;
val.x;
I get the error:
error: ‘union point<3>’ has no member named ‘x’
Even if I change val.x to val.coords::x, I still get the error:
error: ‘union point<3>::coords’ is not a base of ‘union point<3>’
Adding using coords; in the union definition didn't help, either.
Is there any way to accomplish this under the GCC 4.6? Is there a different method of doing this? Is it even possible?
I would suggest using variadic macro to define your union<N> templates.
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
Having done this, you can simply declare/define your various combinations for coordinates (before #undef in this case):
DECLARE_POINT(1, x);
DECLARE_POINT(2, x, y);
DECLARE_POINT(3, x, y, z);
that is equivalent to,
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]; };
It can be used in the same way you asked:
point<3> p;
p.z = 0;
Also, you can put a cross check using some template trickery (static_assert) to check the number arguments(e.g. 1,2,3,...) match the total argument passed (e.g. x,y,z,...).
This line inside your union:
struct coords;
forward-declares the type coords, but there's no struct coords field in your templated union.
Besides, only members of anonymous structures can be accessed as top-level fields of an union. For instance:
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;
I'm not sure you'll be able to do that if you only specialize the inner struct type.
However, this works:
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];
};
There is a number of downsides though; the main one being that you'll have to redefine operator[] for each version of point.
I know how to use templates but I'm no template god, so it's not out of question that a clever trick exists.
I'm using Boost::assign to initialise a vector of structures as follows:
const std::vector<spriteInfo> Resources::hudObjectInfo = boost::assign::list_of
( spriteInfo(FALSE, SCORE_START_X, SCORE_START_Y, CENTER_ALIGN ))
( spriteInfo(FALSE, SCORE_START_X+NUM_DIFF, SCORE_START_Y, CENTER_ALIGN))
... /* and so on */
;
NB. The spriteInfo struct currently looks like this:
struct spriteInfo
{
spriteInfo::spriteInfo(bool i, float x, float y, int align):
invisible(i), x1(x), y1(y), alignment(align){}
bool invisible;
float x1;
float y1;
int alignment;
};
However, I'd like to make a std::vector<int> as a member of spriteInfo.
If I do that, how would the assignment above look? i.e. Can you initialise a vector whilst passing it as a parameter to a constructor?
This should do :
struct spriteInfo
{
spriteInfo(bool i, float x, float y, int align, const std::vector<int> &v):
invisible(i), x1(x), y1(y), alignment(align), something(v) {}
bool invisible;
float x1;
float y1;
int alignment;
std::vector<int> something;
};
int main()
{
const std::vector<spriteInfo> Resources::hudObjectInfo = boost::assign::list_of
( spriteInfo(FALSE, SCORE_START_X, SCORE_START_Y, CENTER_ALIGN, boost::assign::list_of(1)(2)(3)))
( spriteInfo(FALSE, SCORE_START_X+NUM_DIFF, SCORE_START_Y, CENTER_ALIGN, boost::assign::list_of(4)(5)(6)))
;
}
I have a struct that represents a vertex. It has x, y and z fields as well as several others. Recently I came into conclusion that for certain functionality I will need to access the coordinates of the vertex as an array. I didn't want to "pollute" the code with temporary variables or change all places that look like this v.y to this v.coord[1] which is not nice nor elegant. So I thought about using a union. Something like this should work:
struct {
float x,y,z;
} Point;
struct {
union {
float coord[3];
Point p;
};
} Vertex;
This is good, but not perfect. The point class has no point being there. I want to be able to access y coordinate simply by typing v.y (and not v.p.y).
Can you suggest a hack to solve this (or tell me that it is not possible)?
A good C++ approach is to use named accessors that return references to the elements:
class Point {
public:
float& operator[](int x) { assert(x <= 2); return coords_[x]; }
float operator[](int x) const { assert(x <= 2); return coords_[x]; }
float& X() { return coords_[0]; }
float X() const { return coords_[0]; }
float& Y() { return coords_[1]; }
float Y() const { return coords_[1]; }
float& Z() { return coords_[2]; }
float Z() const { return coords_[2]; }
private:
float coords_[3];
};
With this approach, given a Point p;, you can use both p[0] and p.X() to access the initial element of the internal coords_ array.
OK, this should work for you
struct {
union {
float coord[3];
struct
{
float x,y,z;
};
};
} Vertex;
What this code does is that it unions the array with the structure, so they share the same memory. Since the structure doesn't contain a name, it is accessible without a name, just like the union itself.
Can I have a method which takes arguments that are denoted with the same names as the members of the holding class? I tried to use this:
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
x = x;
y = y;
};
};
... but it doesn't seem to work.
Is there any way of accessing the the instance the namespace of which I'm working in, similar to JavaScript's this or Python's self?
It's generally a good idea to avoid this kind of confusion by using a naming convention for member variables. For example, camelCaseWithUnderScore_ is quite common. That way you would end up with x_ = x;, which is still a bit funny to read out loud, but is fairly unambiguous on the screen.
If you absolutely need to have the variables and arguments called the same, then you can use the this pointer to be specific:
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
this->x = x;
this->y = y;
}
};
By the way, note the trailing semi-colon on the class definition -- that is needed to compile successfully.
Yes, you should be able to write this using the "this" keyword (which is a pointer in C++):
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
this->x = x;
this->y = y;
}
}
In C++ the current instance is referenced by the const pointer this.
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
this->x = x;
this->y = y;
};
};