• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
madRenEGadE

Is this a valid usage for unions?

16 posts in this topic

Hello all,

recently I decided to discard my hand-written math library code and use the GLM library.

Because I want to make it "feel" like my own code need some thin wrapper around it. Because performance matters I don't want to
write the wrapper using inheritance like this:

[CODE]
class Vector3 : public glm::dvec3
{
};
[/CODE]

Now I have the idea to use a union and write code like this:

[CODE]
union Vector3
{
public:
Vector3(double x, double y, double z)
: v(x, y, z)
{
}

double x, y, z;

private:
glm::dvec3 v;
};
[/CODE]

Is this valid code (using C++11)? Edited by madRenEGadE
0

Share this post


Link to post
Share on other sites
Access to members of a virtual base and calling virtual functions will typically result in a small performance penalty, but in the kind of inheritance you've shown, there will be none.

The doubles x, y and z in your union all occupy the same memory location. Presumably that's not intended.

I also suspect that you're heading down the road of type punning through the union, which strictly speaking is illegal, though some compilers explicitly support it. Take care.

My recommendation: typedef glm::dvec3 Vector3;
0

Share this post


Link to post
Share on other sites
Partially answering myself.

of course [CODE]
double x, y, z
[/CODE] does not work.

So I have to use something like this:
[CODE]
union Vector3
{
public:
Vector3(double x, double y, double z)
: v(x, y, z)
{
}
inline double x() { return d[0]; }
inline double y() { return d[1]; }
inline double z() { return d[2]; }

private:
double d[3];
glm::dvec3 v;
};
[/CODE]

Actually I wanted to avoid the method calls for accessing the data members...

Are compilers smart enough to optimize this code (this post) so that it performs as fast as the first one (previous post)?
0

Share this post


Link to post
Share on other sites
Using [CODE]
typedef glm::dvec3 Vector3
[/CODE] was my first idea BUT I want things like the cross product to be used as member functions. GLM implements them as
normal functions taking the two vectors as parameters.

But when the inheritance I have suggested does not have any performance penalties I will go that way. Edited by madRenEGadE
0

Share this post


Link to post
Share on other sites
[quote name='madRenEGadE' timestamp='1336590363' post='4938730']

GLM implements them as normal functions taking the two vectors as parameters.
[/quote]

That makes perfect sense I'd say; as a cross product is a pure function, to have it appear to "act upon" any particular vector would be strange. A cross product also has no need to access or manipulate the (non-existent) private state of a vector. Free functions also play nicer with generic code, FWIW.
1

Share this post


Link to post
Share on other sites
Same reasoning (IMO). One input, one output, no dependency on the private state. Edited by edd²
0

Share this post


Link to post
Share on other sites
I don't think you want to be using a union here, it might work one way or another, but I can't see this as being considered good practice

I'd just go with the inheritance if you want to add some of your own functions, I can assure you that the "performance penalty" that could possibly be introduced by it will be least of your worries in the end. Otherwise go for the typedef, clean and simple.

By the way, only worry about optimizing these little things like inheritance overhead if they actually pose a problem, and in this case it'll probably never become a problem. In the end there will be loads of better candidates for optimization before you should even consider looking at overhead caused by language mechanisms.
0

Share this post


Link to post
Share on other sites
[quote name='edd²' timestamp='1336591011' post='4938734']
Same reasoning (IMO). One input, one output, no dependency on the private state.
[/quote]
I think you are right, at least if normalize creates a new vector. But when I really want to normalize the instance normalize is invoked on, it needs access to the state. But maybe that is not the problem as the state is public...


[quote name='Radikalizm' timestamp='1336591033' post='4938735']
I don't think you want to be using a union here, it might work one way or another, but I can't see this as being considered good practice
[/quote]
"Good practice" is enough of a reason for me to not use unions for this [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]

So decision has to be made between "inheritance" and "typedef + free functions" Edited by madRenEGadE
0

Share this post


Link to post
Share on other sites
You might want to look at the coding style for the rest of your code (I assume you're writing a game?) and adapt to what fits best with that so you can save yourself the headache of having to keep different coding styles in mind later on

If there's no other code to speak of and if you're comfortable with it I'd say go with edd's suggestion. Edited by Radikalizm
0

Share this post


Link to post
Share on other sites
Member functions would fit better to the rest of my code. But for the free functions I would rather like to use something like Vector3::normalize(v). So I would need to
use inheritance + static methods?! The typedefs would also be fine but Is it possible to typedef the free functions of glm (never done something like that)?

I think of:
[CODE]
namespace Math
{
typedef glm::dvec3 Vector3;
typedef glm::normalize Normalize;
};
[/CODE]

Maybe I could just write inline functions for my desired "renaming":

[CODE]
namespace Math
{
inline Vector3 Normalize(const Vector3& v)
{
return glm::normalize(v);
}
}
[/CODE] Edited by madRenEGadE
0

Share this post


Link to post
Share on other sites
The typedef keyword is for use with datatypes only

Inlining would work, but IMO you're going to end up doing lots of work wrapping all the functions provided by glm without any real purpose
0

Share this post


Link to post
Share on other sites
[quote name='Radikalizm' timestamp='1336592708' post='4938745']
Inlining would work, but IMO you're going to end up doing lots of work wrapping all the functions provided by glm without any real purpose
[/quote]
The purpose for me is that all my code looks consistent and that I could change the math library later on. And fortunately is is not that much work because I would just wrap the functions I actually need.

Thanks to both of you for the help [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
0

Share this post


Link to post
Share on other sites
Good OOP practice prefers to minimize interfaces that have access to internal state (including 'friend' functions or 'friend' classes), and prefers non-member, non-friend functions located in the same namespace--because of Koenig Lookup, these functions are still effectively a part of the class interface, but better promote encapsulation.

True member functions should be used to provide the minimum necessary interface needed to implement higher-level interface functions or when the object is itself modified by the operation. Using these member functions should be the preferred means of implementing higher-level functionality through non-member, non-friend functions, but non-member friend functions can be used in cases when a function requires non-modifying access to object internals (though this usually indicates that your "true member" interface is lacking) using a const reference to the object. Edited by Ravyne
1

Share this post


Link to post
Share on other sites
Really good explanation!!!

So best choice for e.g vector normalization would be a free function in the Math namespace which takes a const reference to a vector and to have a member function
which does not take parameters but normalizes the vector instance itself?
0

Share this post


Link to post
Share on other sites
[quote name='madRenEGadE' timestamp='1336590245' post='4938729']
Actually I wanted to avoid the method calls for accessing the data members...

Are compilers smart enough to optimize this code (this post) so that it performs as fast as the first one (previous post)?
[/quote]
[quote name='madRenEGadE' timestamp='1336590363' post='4938730']
Using [CODE]
typedef glm::dvec3 Vector3
[/CODE] was my first idea BUT I want things like the cross product to be used as member functions. GLM implements them as
normal functions taking the two vectors as parameters.

But when the inheritance I have suggested does not have any performance penalties I will go that way.
[/quote]

Yes, if you inherit a value type, and always use the object via the derived class and retain the POD-likeness of the object (no custom ctors/dtors/assignments or copy-ctors), you will not have to use a virtual dtor, and there will be no performance penalties.

If you are interested in having a look at another library which does give you accesses to vector .x/.y/.z without function calls, and has .Cross() as a member function (but also as a freestanding function), see my [url="http://clb.demon.fi/MathGeoLib/"]MathGeoLib[/url] library. The float3 class reference is [url="http://clb.demon.fi/MathGeoLib/docs/float3_summary.php"]here[/url].
0

Share this post


Link to post
Share on other sites
I'd do it something like this (syntax may not be exact since I don't have a compiler in front of me):

[code]
namespace math {
class vector {
...
public:
vector& normalized() {
float inverse_length = 1 / this.length();

this.x *= inverse_length;
this.y *= inverse_length;
this.z *= inverse_length;

return *this;
}
...
};

vector& normalized_copy(vector to_normalize) { // notice I take this by value
return to_normalize.normalized();
}
}
[/code]

Here, the non-member, non-friend function takes the vector by value and then uses the member function normalize() to do the work. This pattern of passing in by value, modifying that object, and returning it modified and by reference enables the Return Value Optimization (RVO), so it not only re-uses the member implementation, but is efficient as well. RVO basically eliminates redundant copies of the object. Using a similar pattern, you can implement binary +, -, *, / and other operators as non-member, non-friend functions by re-using the unary member operators for +=, -=, *=, /=, etc. Edited by Ravyne
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0