Re: is this portable, conforming to standard, elegant?
On Feb 15, 1:49 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
Craig Scott wrote:
On Feb 15, 2:04 am, "Emmanuel Deloget" <log...@free.fr> wrote:
On 13 f=E9v, 20:00, "Alexei Polkhanov" <apolkha...@relic.com> wrote:
On Feb 9, 5:05 pm, "Craig Scott" <audiofana...@gmail.com> wrote:
class U
{
// Normally, x,y,z would be private, but OP needs them
// to be public
public:
float x;
float y;
float z;
// operator[] should be public
public:
// Should also provide a const version of this
float& operator[](int index)
{
if (index == 0)
return x;
else if (index == 1)
y;
else if (index == 2)
return z;
else
// Throw exception or something else appropriate
};
};
Personally, to me this then becomes the "best compromise" solution=
to
the original poster's problem. It allows clients to continue using
x,y,z member variables but also access using array index notation.=
It
Agree, this solution is much better, however I was under impression
that
using "union" had to be part of the solution since it was part of the
question.
- Alexei.
I (really) dislike being the one who says "there is a better solution,
look at mine", but that's going to be what I'm going to do - as the
solution I proposed is quite elegant, standard-proof, and doesn't
require any (endless?) if/then/if/then/else block. The static array of
pointer to members allows a direct access to the variable you need, is
extensible, and doesn not add any space to the class itself, since
it's a class static. As I said, I'm not really sure about the init
time of this array, but given the fact that it's a static POD array,
it should be initialized quite early. Further refinement (throwing a
out_of_range exception) is not difficult to implement (as it only
requires a test against the size of the array, and the mandatory throw
statement). The simplicity of operator[] will make this method a good
candidate for inlining, so in the end the code is quite efficient.
Now, there may be some problems I haven't seen (I don't see every
problem) - if you find some, please tell me.
Probably the biggest weakness is that using the static array makes
your class unsuitable for use in a multi-threaded application. If your
app is single threaded, then it's fine.
I am not sure about that.
The proposed solution was essentially this:
struct Vector3 {
float x, y, z;
float const & operator[](unsigned int i) const {
static float Vector3::* const proxy[3] =
{ &Vector3::x, &Vector3::y, &Vector3::z };
return (*this).*proxy[i];
}
float & operator[] ( unsigned int i ) {
return
( const_cast<float&>
( const_cast<Vector3 const *>(this)->operator[](i) ) );
}
};
#include <iostream>
int main ( void ) {
Vector3 a;
a[1] = 2;
std::cout << a.y << '\n';
}
The static array is const. It never changes, so apart from initialization
issues, I do not see a problem in multithreading (probably, I am very nai=
ve
here:-). If there is a problem, one could make operator[] atomic using so=
me
RAII mutex wrapper so that reads to the static data is properly serialize=
d.
That would take care of the initialization issue, as well. Code could look
like this:
class Vector3 {
static some_lock_type the_lock;
public:
float x, y, z;
float const & operator[](unsigned int i) const {
SomeLockAcquiringWrapper the_guard ( the_lock );
static float Vector3::* const proxy[3] =
{ &Vector3::x, &Vector3::y, &Vector3::z };
return (*this).*proxy[i];
}
float & operator[] ( unsigned int i ) {
return
( const_cast<float&>
( const_cast<Vector3 const *>(this)->operator[](i) ) );
}
};
However, it might be to costly to do that :-(
Your static array is const but you cast away the const-ness with your
non-const operator[], so clients would be free to try to change the
contents with potentially lethal results. The use of locking will, of
course, get you around the data corruption issue, but I doubt clients
of the class would be expecting to pay the penalty of locking just to
access a class like this. I certainly wouldn't.
--
Computational Fluid Dynamics, CSIRO (CMIS)
Melbourne, Australia