Vector class design

Started by
8 comments, last by CmpDev 17 years, 5 months ago
Hi! I'm currently making a game engine and I've just made the classes Vector2, Vector3 and Vector4. I have two questions : First, I have templated my vector classes so they can hold any type of data. I am wondering if I'm going into too much trouble doing so. That would mean having also templated matrix classes and all math operations templated. Should I just keep it to floats only? Second, I am using anonymous unions and structures in my vector :

class Vector4
{
public:
  union
  {
    float i[4];
    struct { float x, y, z, w; };
    struct { float r, g, b, a; };
  };
};

I do know that anonymous unions are not standard C++ but they are very practical. I'm not currently intending to port my engine but that might happen. In this case, should I completely avoid anonymous unions and structs? I've seen OGRE's vector classes using them and it is still cross-platform. Can I find Linux and Macintosh compilers supporting this feature? Thanks a lot!
Advertisement
Quote:I am wondering if I'm going into too much trouble doing so.

Too much trouble? It should be about the same unless you plan on supporting SIMD for multiple types (MMX for integers, SSE for floats, etc.).

Quote:I do know that anonymous unions are not standard C++ but they are very practical.

I'm not sure I get you. How are they practical? You'll most likely get padding problems if you try having references/pointers to different members of the union at the same time.

EDIT: If you don't know how to provide both by name (x,y,z) and indexed access, look at this standard C++ code with well-defined behavior.

Quote:In this case, should I completely avoid anonymous unions and structs?

Should I avoid using "u" instead of "you" when writing English? Of course, both are understandable, the former will however make me look like an immature child, while the latter make me seem like I'm actually using English, instead of pretending I am.

Quote:I've seen OGRE's vector classes using them and it is still cross-platform.

I might get flamed for this, but Ogre isn't the best C++ code available. The very first line of every header file isn't guaranteed to be valid (all identifiers starting with _ followed by uppercase or another _ is reserved for the compiler).

Also cross-platformness means it works on more than one platform (this could just be two) and how well isn't defined.

Do you expect Vector4::i[0] to be equal to Vector4::x? Well it isn't guaranteed to, actually nothing is guaranteed since you aren't programming C++ anymore. One of them could be padded, debug information could be inserted, etc. Imagine all the nights you're going to stay up trying to first figure out such a bug and then force ALL your compilers to behave properly when given improper code.

Also why is r, g, b and a members of the vector? This isn't a color, and you'll run into many problems if you try to pretend it is.
Original post by Trillian

Second, I am using anonymous unions and structures in my vector :
class Vector4{public:  union  {    float i[4];    struct { float x, y, z, w; };    struct { float r, g, b, a; };  };};

I do know that anonymous unions are not standard C++ ...

Thanks a lot!

Anonymous unions are standard C++ but anonymous unions with nested types are not. So the above could be written:
class Vector4{public:  union  {    float i[4];    float x, y, z, w;    float r, g, b, a;  };};
Quote:Original post by CmpDev
Anonymous unions are standard C++ but anonymous unions with nested types are not. So the above could be written:
*** Source Snippet Removed ***
Yes, you could write it that way, but the result would be completely different.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
I think that I am going to drop the template idea and use your array indexing technique. This is a good compromise for me so thanks a lot!

As for the colors, do you think I should do a similar class for colors containing r,g,b,a floats? I found grouping them in a single class pratical but I understand it might to be the greatest idea.

Thanks a lot for your clear reply.
I'm ignorant as to why it would be different Promit could you explain please.
Quote:Original post by Trillian
I think that I am going to drop the template idea and use your array indexing technique. This is a good compromise for me so thanks a lot!

You could still use templates, but of course floats are going to work fine for most purposes.

Quote:As for the colors, do you think I should do a similar class for colors containing r,g,b,a floats? I found grouping them in a single class pratical but I understand it might to be the greatest idea.

The problem here is that even though the intuitive representation for both of them is similar their purpose, interface and type shouldn't be the same.

One of the reasons for using an object of Vector4 instead of just an array is type-safety. You are guaranteed that when you ask for an array you won't accidentally get passed a vector, and when asking for a vector you won't accidentally get an array. Now when expecting a color you aren't sure whether the user accidentally passed a vector. Also your colors will have access to stuff like vector addition, cross product, normalization, etc. even though you would never want to do that on colors. Even if you wanted to you would choose a more appropriate name for colors (additive_blending could be a color function, but vectors shouldn't have access to this). How would you handle overloading a function taking either a color or a vector? This won't be possible, not even at runtime with the current definition.

It gets way too easy to confuse vectors and colors. Additionally you might need to chance the representation for one of them later, what if suddenly you want vectors of double extended precision (it might be the native format for your FPU) and colors of single precision (to reduce BUS traffic).

So even though they might seem similar, they aren't, and they should be separated. Initially a color could just be a Vector4 internally, but with the possibility to change it later:
class ColorARGB{  Vector4 data;public:  // ...};



Quote:Original post by CmpDev
I'm ignorant as to why it would be different Promit could you explain please.

Because i[0], r, g, b, a, x, y, z and w all occupy the same space in memory.
EDIT: Too slow, that is what happens when you try to quote the standard

Quote:Original post by CmpDev
I'm ignorant as to why it would be different Promit could you explain please.


float i[4];float x, y, z, w;float r, g, b, a;


Is equivalent to:

float i[4];float x;float y;float z;float w;float r;float g;float b;float a;


See first page of Declarators (chapter 8) in the C++ standard.
Quote:A declarator declares a single object, function, or type, within a declaration. The init-declarator-list appearing in a declaration is a comma-separated sequence of declarators, each of which can have an initializer.
    init-declarator-list:        init-declarator:        init-declarator-list , init-declarator    init-declarator:       declarator initializeropt

...
Each init-declarator in a declaration is analyzed separately as if it was in a declaration by itself85).
...
85) A declaration with several declarators is usually equivalent to the corresponding sequence of declarations each with a single declarator. That is
T D1, D2, ... Dn;

is usually equvalent to
T D1; T D2; ... T Dn;

where T is a decl-specifier-seq and each Di is a init-declarator. The exception occurs when a name introduced by one of the declarators hides a type name used by the dcl-specifiers, so that when the same dcl-specifiers are used in a subsequent declaration, they do not have the same meaning, as in
struct S { ... };S S, T; // declare two instances of struct S

which is not equivalent to
struct S { ... };S S;S T; // error
Quote:Original post by Brother Bob
Quote:Original post by CmpDev
I'm ignorant as to why it would be different Promit could you explain please.

Because i[0], r, g, b, a, x, y, z and w all occupy the same space in memory.


lol that was too simple, why didn't I think of that:(

This topic is closed to new replies.

Advertisement