LR said:
Kai-Uwe Bux said:
Jerry said:
Is this safe:
class vector
{
public:
float x, y, z;
float *pointer() { return &x; }
};
vector v;
v.pointer()[0] = 123862; // Set x
v.pointer()[1] = 227364; // Set y
v.pointer()[2] = 3495; // Set z
(Are x, y and z always ordered in the memory like members of an array?)
As has already been pointed out, they can be separated by padding. You
can achieve (nearly) the same thing by reversing the roles though:
struct vector {
float pointer[3];
float &x, &y, &z;
vector() : x(pointer[0]), y(pointer[1]), z(pointer[2]) {}
};
That can be costly.
What about:
struct vector {
float x,y,z;
float &operator[](const size_t index) {
if(index > 2)
throw std:
ut_of_range("Index out of range");
return
index == 0 ? x :
index == 1 ? y :
z;
}
};
Can be used like:
vector v;
v[0] = 123862;
v[1] = 227364;
v[2] = 3495;
That's fine. I gave a similar solution elsethread.
One should remark, however, that overloading operator[] is not really all
that useful. The nice thing about the original idea of having an array of
values is that one could use the STL algorithms on the sequence. For
instance, one could use std::lexicographic_compare() to implement operator<
for this vector thingy.
I guess if you really have to do something like:
v.pointer()[0] = ...
you could have pointer return some object that has an operator[] member.
I'm curious though as to why not either have member functions like:
float &xr() { return x; }
float &yr() { return y; }
float &zr() { return z; }
Personally, I like that (one should add const versions of these). The
drawback is that certain expressions get cluttered with empty parentheses
pairs. However, it allows for all that is needed.
or have a ctor like:
vector(const float f1, const float f2, const float f3)
: x(f1), y(f2), z(f3)
{}
That's not "or". One should have this _and_ some of the other stuff.
Thus, here is a new proposal:
#include <cstddef>
#include <cassert>
#include <algorithm>
class point {
float coordinate [3];
public:
typedef float value_type;
typedef value_type & reference;
typedef value_type const & const_reference;
typedef value_type * pointer;
typedef value_type const * const_pointer;
reference x ( void ) {
return ( coordinate[0] );
}
const_reference x ( void ) const {
return ( coordinate[0] );
}
reference y ( void ) {
return ( coordinate[1] );
}
const_reference y ( void ) const {
return ( coordinate[1] );
}
reference z ( void ) {
return ( coordinate[2] );
}
const_reference z ( void ) const {
return ( coordinate[2] );
}
point ( float x_, float y_, float z_ )
{
x() = x_;
y() = y_;
z() = z_;
}
pointer begin ( void ) {
return ( &coordinate[0] );
}
const_pointer begin ( void ) const {
return ( &coordinate[0] );
}
pointer end ( void ) {
return ( begin() + 3 );
}
const_pointer end ( void ) const {
return ( begin() + 3 );
}
reference operator[] ( std::size_t i ) {
assert ( i < 3 );
return ( coordinate
);
}
const_reference operator[] ( std::size_t i ) const {
assert( i < 3 );
return ( coordinate );
}
};
bool operator< ( point const & lhs, point const & rhs ) {
return ( std::lexicographical_compare( lhs.begin(), lhs.end(),
rhs.begin(), rhs.end() ) );
}
#include <iostream>
#include <iomanip>
int main ( void ) {
point p ( 1, 1, 1 );
point q ( 1, 1, 1.1 );
std::cout << std::boolalpha << ( p < q ) << '\n';
}
Alternatively, one can cook up an iterator class to go with the other
solutions based upon doing something funny (like a switch statement) with
operator[].
Best
Kai-Uwe Bux