Is this a valid usage for unions?

Started by
15 comments, last by Ravyne 11 years, 11 months ago
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:

namespace Math
{
typedef glm::dvec3 Vector3;
typedef glm::normalize Normalize;
};


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


namespace Math
{
inline Vector3 Normalize(const Vector3& v)
{
return glm::normalize(v);
}
}
Advertisement
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

I gets all your texture budgets!


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

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 smile.png
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.

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

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?

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)?


Using
typedef glm::dvec3 Vector3
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.


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 MathGeoLib library. The float3 class reference is here.
I'd do it something like this (syntax may not be exact since I don't have a compiler in front of me):


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();
}
}


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.

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

This topic is closed to new replies.

Advertisement