|
Boost : |
From: Geoffrey Irving (irving_at_[hidden])
Date: 2006-09-21 13:33:32
On Thu, Sep 21, 2006 at 06:18:10PM +0200, Theodore Papadopoulo wrote:
> On Thu, 2006-09-21 at 08:54 -0400, Michael Fawcett wrote:
>
> > You can get around this using something like this:
> >
> > template< typename T >
> > struct Vector4 {
> >
> > typedef size_t size_type;
> >
> > private:
> >
> > typedef T Vector4<T>::* const vec[4];
> >
> > static const vec v;
> >
> > public:
> >
> > T x, y, z, w;
> >
> > Vector4(T _x = 0, T _y = 0, T _z = 0, T _w = 0):
> > x(_x), y(_y), z(_z), w(_w) {}
> >
> > const T& operator[](size_type i) const {
> > return this->*v[i];
> > }
> >
> > T& operator[](size_type i) {
> > return this->*v[i];
> > }
> >
> > };
> >
> > template< typename T >
> > const typename Vector4<T>::vec Vector4<T>::v = { &Vector4<T>::x,
> > &Vector4<T>::y, &Vector4<T>::z, &Vector4<T>::z };
> >
> > Here's the original discussion from gamedev.net
> > http://www.gamedev.net/community/forums/topic.asp?topic_id=261920
> >
> > This wasn't written by me, I just remembered it from there and thought
> > it might be interesting to you.
This code is much too hard for the compiler to optimize. In order to
handle a loop like
for(int i=0;i<n;i++) f(V[i]);
where n at runtime could be either 2 or 3, the compiler would have to
independently determine the identity vec[i+1] = vec[i]+1. There's no
way that would happen on any compiler now or in the immediate future.
> Interesting ! But I would certainly prefer the straightforward array
> implementation and an enum {X,Y,Z,Z} that allows the notation
>
> V[X] or V(X) (depending on your preference). The only fear I may have
> with your proposal is that by having complicated accesses, the compiler
> might not be able to do some optimizations.
This scheme means you can't have a vector called X, which happens to be
one of the most commonly used vector names in my code (X for position,
V for velocity).
I don't think there's any reason to overthink this. The simple scheme
works:
template<class T> class vector3
{
public:
T x,y,z;
vector3()
{
assert(&z == &x+3);
}
T& operator[](unsigned i)
{assert(i<3);return (&x)[i];}
};
It can probably even be considered standard compliant: if the assert
doesn't hit, I'm pretty sure the standard guarantees that the code
is correct.
If I run the following code through gcc 4.0.1
vector3<float> X;
X.y=3;
X[2]=4; // critical line
std::cout<<X.x;
the compiler unpacks X into fields and complains about X$x being
used uninitialized iff I comment out the critical line, so there
shouldn't be any penalty to the existence of operator[] unless you
use it in on a given vector.
As a side note, is it possible to write that with a STATIC_ASSERT?
Geoffrey
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk