🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

problem moving visual studio project to xcode

Started by
7 comments, last by xilef 15 years, 2 months ago
i am currently attempting to move my work from windows to osx and am having problems compiling my vector classes . the following code

struct v2
{
	union
	{
		struct{ f32 v[2]; };
		struct{ f32 x, y; };
	};
	v2(void)												{}
	v2(const f32 a, const f32 b)							{x  = a;   y  = b;}
	void operator =  (const f32 a)							{x  = a;   y  = a;}
	void operator -= (const f32 a)							{x -= a;   y -= a;}
	void operator += (const f32 a)							{x += a;   y += a;}
	void operator *= (const f32 a)							{x *= a;   y *= a;}
	void operator /= (const f32 a)							{x /= a;   y /= a;}
	void operator =  (const v2& a)							{x  = a.x; y  = a.y;}
	void operator -= (const v2& a)							{x -= a.x; y -= a.y;}
	void operator += (const v2& a)							{x += a.x; y += a.y;}
	void operator *= (const v2& a)							{x *= a.x; y *= a.y;}
	void operator /= (const v2& a)							{x /= a.x; y /= a.y;}
};

struct v3
{
	union
	{
		struct{ f32 v[3]; };
		struct{ f32 x, y, z; };
		struct{ v2  xy; f32 z; };
	};
	v3(void)												{}
	v3(const f32 a)											{x  = a;   y  = a;   z  = a;}
	v3(const f32 a, const f32 b, const f32 c)				{x  = a;   y  = b;   z  = c;}
	void operator =  (const f32 a)							{x  = a;   y  = a;   z  = a;}
	void operator -= (const f32 a)							{x -= a;   y -= a;   z -= a;}
	void operator += (const f32 a)							{x += a;   y += a;   z += a;}
	void operator *= (const f32 a)							{x *= a;   y *= a;   z *= a;}
	void operator /= (const f32 a)							{x /= a;   y /= a;   z /= a;}
	void operator =  (const v3& a)							{x  = a.x; y  = a.y; z  = a.z;}
	void operator -= (const v3& a)							{x -= a.x; y -= a.y; z -= a.z;}
	void operator += (const v3& a)							{x += a.x; y += a.y; z += a.z;}
	void operator *= (const v3& a)							{x *= a.x; y *= a.y; z *= a.z;}
	void operator /= (const v3& a)							{x /= a.x; y /= a.y; z /= a.z;}
};


gives this error when compiling in xcode 3.0 error: member 'v2 v3::<anonymous union>::<anonymous struct>::xy' with constructor not allowed in anonymous aggregate is there any neat way of fixing this - i.e. not resorting to naming the unioned structures? the only other suggested fix i have heard was to remove the constructors from the class and use a factory constructor instead . i have little experience with factory objects - but from what i understand it would involve having a "vectorFactory" object which i would need to call a function of whenever i wanted to create a vector . if this is the case then it would seemingly be an even clumsier solution than having to name the unioned structures any help would be appreciated thanks
Advertisement
First things first, you really need to reconsider your Vector classes, some of the methods you have implemented (like + and - of a scaler value) make zero sense, and your self-modifying forms (+=, -=, *=, /=) need to return a reference to itself, or you violate the normal expected behavior of those operators. You're going to need value-return forms (+, -, *, /) which should be implemented as non-member, non-friend methods in the same namespace as your classes.

This is meant to be encouraging, rather than discouraging, but this is really the worst vector class design I've ever seen. In some places you make mistakes that go beyond the usual noob design decisions, and in some places you haven't even gotten to that point yet.

throw table_exception("(? ???)? ? ???");

i guess it is kind of retarded to + and - scalars :) must've been one of those thoughtless completest things . i'll add the reference returns - i already had the +-*/ ops in my vector.cpp file

thanks for the general advice - but would you happen to know how to solve my initial query?
In GCC, which is what XCode uses to compile, this is not allowed -- Microsoft allows it, but it is supported through a non-standard extension.

You're right that adding factories is a clumsy solution, but again, I think you're trying to create a solution which has no tangible benefit to anyone, so its bound to be clumsy.

So, the real question is "What do you really gain from that third anonymous structure?"

If you tell us what benefit you're seeking, we can perhaps suggest a better approach. The only thing I can think of, without knowing what's rolling around inside your head, is that you want to keep a v2 handy to be passed around, and if that's the case you may be better served by supplying explicit conversion functions.


It seems to me that you're suffering from a bout of over-engineering, which you, yourself, allude to, calling it "completest". Remember that designing a class isn't about providing anything everyone could possibly want regardless of its merit... a good API is complete, but also unwavering in its focus, and only interface elements that are of true merit should be implemented -- anything less is to be incomplete, and anything more is to become bloated and unfocused. An API must serve the needs of its users, rather than the technical whims of its creator. Therefore, to design an interface properly, you must think like your users, and resist the urge to wantonly add or innovate without reason or merit.

I know all that is very Zen sounding, but its true, so you should seek to embrace it.

throw table_exception("(? ???)? ? ???");

Also of note, even if you solve this issue, I think you'll have another issue on your hands, though I'm uncertain.

You see, you still have two different v3::<anonymous-union>::<anonymous-struct>::z members lying around (in the second and third structures), and even though they presumably occupy the same location in memory, I believe the compiler will still see this conflict as an irresolvable name collision. Presuming you ever get past your original issue in a manner that is un-marred to your satisfaction, you're going to have to change one of their names, thus introducing another stylistic wart.

In my opinion you're far better off getting rid of the third structure altogether.

throw table_exception("(? ???)? ? ???");

perhaps it is over-engineering - but i thought of it more as a convenience thing . there are numerous occasions when dealing with vectors and matrices where i find myself wanting to access a subset of the data - i.e. i quite often only want to access the xyz components of a vec4 ... simply adding a struct to the union seemed like a neater solution than having a function to return a vec3 of the first 4 elements
The typical approach to that is to provide some of the following:

A Vector2 constructor which takes as its parameter a Vector3.
A Vector3 method which returns a Vector3 by value -- e.g. Vector3.ToVector2()
An explicit conversion from Vector3 to Vector2 -- e.g. Vector3.operator(Vector2)()

You might be worried about efficiency, but I think in most, or at least many, cases where you would want to access such a subset of data that you are creating a copy of it anyhow -- Such as when passing it to a function as a value parameter or setting a local variable equal to it for convenience -- and so you'd have a greater chance at optimizing these cases by actually treating them as what they are, rather than pretending they are something else.

In the remaining cases where you really want to treat the first two elements as if it were a Vector2 already constructed in memory, you're either forced to name the anonymous aggregate, or to create some kind of proxy object that, when cast from a Vector3, would provide the data view you are after -- however you would have to be very aware of how the Vector3 object was actually laid out in memory, including any padding that the compiler may have inserted.

Once again, I do think this is more trouble than its worth, and my own vector and matrix routines get by just fine without it.

throw table_exception("(? ???)? ? ???");

Couldn't you make your v2 and v3 structs unions instead? IIRC, unions can contain member functions, but can't have virtual functions and be base classes. But it seems like that would work for you.
i could but then that would increase the memory footprint

it seems there is no similarly elegant way of allowing for this kind of access with gcc . i guess i will just strip it out - it's really no big loss :)

thanks for all the advice though

This topic is closed to new replies.

Advertisement