union float[3] and x,y,z

G

Gernot Frisch

Uhm...
Is there any way of making
float pos[3];
a union of
float x,y,z;

somehow, so I can use:


mything[0] = mything.y;
instead of mything.x = mything.y

Thanks in advice,
 
A

Alexander Dong Back Kim

Uhm...
Is there any way of making
float pos[3];
a union of
float x,y,z;

somehow, so I can use:

mything[0] = mything.y;
instead of mything.x = mything.y

Thanks in advice,

Hi Gernot,

Just a thought. How about making a structure and overriding operators?


Cheers,
 
V

Victor Bazarov

Gernot said:
Uhm...
Is there any way of making
float pos[3];
a union of
float x,y,z;

somehow, so I can use:


mything[0] = mything.y;
instead of mything.x = mything.y

Thanks in advice,

Hasn't this been discussed here a couple of times over the past
two-three months? No, there is no sense in making a union. The
only way you can manage that is if you stuff 'x', 'y', and 'x' in
some kind of struct inside that union. In structs members can
have padding, and in arrays they don't. So, it is conceivable
that your union trick is not going to work. A solution might be

struct Blah {
float pos[3];
float &x, &y, &z;
Blah() : x(pos[0]), y(pos[1]), z(pos[2]) {}
};

which makes it non-POD (members that are references). Or agree
to define 'x' as a function:

struct Blah {
float pos[3];
float& x() { return pos[0]; }
float x() const { return pos[0]; }
};

In any case, search the archives for "union padding array" and
some other keywords you can come up with.

V
 
G

Guest

Uhm...
Is there any way of making
float pos[3];
a union of
float x,y,z;

somehow, so I can use:


mything[0] = mything.y;
instead of mything.x = mything.y

No, however you can do something like this:

struct thing
{
float arr[3];
float& x;
float& y;
float& z;

thing() : x(arr[0]), y(arr[1]), z(arr[2]) {}
};

Which allows you to access x through either t.x or through t.arr[0]
where t is an object of type thing:

int main()
{
thing t;
t.x = 1;
t.y = 2;
t.arr[2] = 3;

int i = 0;
}

If you want to be able to use t[0] instead of t.arr[0] you have to
overload the [] operator as Alexander Dong Back Kim suggested.
 
V

Victor Bazarov

Erik said:
Uhm...
Is there any way of making
float pos[3];
a union of
float x,y,z;

somehow, so I can use:


mything[0] = mything.y;
instead of mything.x = mything.y

No, however you can do something like this:

struct thing
{
float arr[3];
float& x;
float& y;
float& z;

thing() : x(arr[0]), y(arr[1]), z(arr[2]) {}
};

Which allows you to access x through either t.x or through t.arr[0]
where t is an object of type thing:

int main()
{
thing t;
t.x = 1;
t.y = 2;
t.arr[2] = 3;

int i = 0;
}

If you want to be able to use t[0] instead of t.arr[0] you have to
overload the [] operator as Alexander Dong Back Kim suggested.

Actually, could still do that if you do this trick:

struct thing {
float x, y, z;
struct thing_indexing {
thing& t;
thing_indexing(thing& t) : t(t) {}
float& operator[](int i) {
return i < 2 ? i < 1 ? t.x : t.y : t.z;
}
} arr;
thing() : arr(*this) {}
thing& operator=(thing const& t) {
x = t.x;
y = t.y;
z = t.z;
}
};

int main() {
thing t;
t.x = 3.1415926;
t.arr[1] = t.x;
}

RATS! I got pulled in and am writing code when I didn't want to....

V
 
G

Guest

Erik said:
Uhm...
Is there any way of making
float pos[3];
a union of
float x,y,z;

somehow, so I can use:


mything[0] = mything.y;
instead of mything.x = mything.y

No, however you can do something like this:

struct thing
{
float arr[3];
float& x;
float& y;
float& z;

thing() : x(arr[0]), y(arr[1]), z(arr[2]) {}
};

Which allows you to access x through either t.x or through t.arr[0]
where t is an object of type thing:

int main()
{
thing t;
t.x = 1;
t.y = 2;
t.arr[2] = 3;

int i = 0;
}

If you want to be able to use t[0] instead of t.arr[0] you have to
overload the [] operator as Alexander Dong Back Kim suggested.

Actually, could still do that if you do this trick:

struct thing {
float x, y, z;
struct thing_indexing {
thing& t;
thing_indexing(thing& t) : t(t) {}
float& operator[](int i) {
return i < 2 ? i < 1 ? t.x : t.y : t.z;
}
} arr;
thing() : arr(*this) {}
thing& operator=(thing const& t) {
x = t.x;
y = t.y;
z = t.z;
}
};

int main() {
thing t;
t.x = 3.1415926;
t.arr[1] = t.x;
}

RATS! I got pulled in and am writing code when I didn't want to....

Sorry, but I just cannot understand the reason for this construct. To me
it looks like it provides exactly the same functionality as my code,
except that I used an array and you used a struct with an overloaded []
operator. Please, enlighten me.
 
V

Victor Bazarov

Erik said:
Erik said:
On 2007-09-25 14:26, Gernot Frisch wrote:
Uhm...
Is there any way of making
float pos[3];
a union of
float x,y,z;

somehow, so I can use:


mything[0] = mything.y;
instead of mything.x = mything.y

No, however you can do something like this:

struct thing
{
float arr[3];
float& x;
float& y;
float& z;

thing() : x(arr[0]), y(arr[1]), z(arr[2]) {}
};

Which allows you to access x through either t.x or through t.arr[0]
where t is an object of type thing:

int main()
{
thing t;
t.x = 1;
t.y = 2;
t.arr[2] = 3;

int i = 0;
}

If you want to be able to use t[0] instead of t.arr[0] you have to
overload the [] operator as Alexander Dong Back Kim suggested.

Actually, could still do that if you do this trick:

struct thing {
float x, y, z;
struct thing_indexing {
thing& t;
thing_indexing(thing& t) : t(t) {}
float& operator[](int i) {
return i < 2 ? i < 1 ? t.x : t.y : t.z;
}
} arr;
thing() : arr(*this) {}
thing& operator=(thing const& t) {
x = t.x;
y = t.y;
z = t.z;
}
};

int main() {
thing t;
t.x = 3.1415926;
t.arr[1] = t.x;
}

RATS! I got pulled in and am writing code when I didn't want to....

Sorry, but I just cannot understand the reason for this construct. To
me it looks like it provides exactly the same functionality as my
code, except that I used an array and you used a struct with an
overloaded [] operator. Please, enlighten me.

It was a facetious suggestion, so that the OP could use 'arr' to get
to the members, not just the indexing operator (working from your
original suggestion to use 'thing.arr[0]' syntax).

V
 
J

Jim Langston

Victor Bazarov said:
Erik said:
Erik Wikstr?m wrote:
On 2007-09-25 14:26, Gernot Frisch wrote:
Uhm...
Is there any way of making
float pos[3];
a union of
float x,y,z;

somehow, so I can use:


mything[0] = mything.y;
instead of mything.x = mything.y

No, however you can do something like this:

struct thing
{
float arr[3];
float& x;
float& y;
float& z;

thing() : x(arr[0]), y(arr[1]), z(arr[2]) {}
};

Which allows you to access x through either t.x or through t.arr[0]
where t is an object of type thing:

int main()
{
thing t;
t.x = 1;
t.y = 2;
t.arr[2] = 3;

int i = 0;
}

If you want to be able to use t[0] instead of t.arr[0] you have to
overload the [] operator as Alexander Dong Back Kim suggested.

Actually, could still do that if you do this trick:

struct thing {
float x, y, z;
struct thing_indexing {
thing& t;
thing_indexing(thing& t) : t(t) {}
float& operator[](int i) {
return i < 2 ? i < 1 ? t.x : t.y : t.z;
}
} arr;
thing() : arr(*this) {}
thing& operator=(thing const& t) {
x = t.x;
y = t.y;
z = t.z;
}
};

int main() {
thing t;
t.x = 3.1415926;
t.arr[1] = t.x;
}

RATS! I got pulled in and am writing code when I didn't want to....

Sorry, but I just cannot understand the reason for this construct. To
me it looks like it provides exactly the same functionality as my
code, except that I used an array and you used a struct with an
overloaded [] operator. Please, enlighten me.

It was a facetious suggestion, so that the OP could use 'arr' to get
to the members, not just the indexing operator (working from your
original suggestion to use 'thing.arr[0]' syntax).

Isn't this functionality what the OP asked for, what Alexander was
suggesting?

struct thing
{
float x, y, z;
float& operator[]( size_t Index )
{
switch ( Index )
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
default:
throw "Bad Index";
}
}
};

I'm confused where this "arr" come in, I don't see it in the OP.
 
K

Kai-Uwe Bux

Gernot said:
Uhm...
Is there any way of making
float pos[3];
a union of
float x,y,z;

somehow, so I can use:


mything[0] = mything.y;
instead of mything.x = mything.y

Why stop there? why not make point a container:

#include <cstddef>
#include <cassert>
#include <iterator>
#include <functional>
#include <algorithm>

template < typename T >
struct const_qualifier {

typedef T type;

typedef T mutable_type;
typedef T const const_type;

static bool const is_const = false;

};

template < typename T >
struct const_qualifier< T const > {

typedef T const type;

typedef T mutable_type;
typedef T const const_type;

static bool const is_const = true;

};

template < typename T, bool is_const >
struct pointer_parameter;

template < typename T >
struct pointer_parameter<T,true> {

typedef T const * type;

};

template < typename T >
struct pointer_parameter<T,false> {

typedef T * type;

};

template < typename T, bool is_const >
struct reference_parameter;

template < typename T >
struct reference_parameter<T,true> {

typedef T const & type;

};

template < typename T >
struct reference_parameter<T,false> {

typedef T & type;

};

template < typename Target, typename C, bool is_const >
struct indexing_iterator_base;

template < typename Target, typename C >
struct indexing_iterator_base<Target,C,false> :
public std::iterator< std::random_access_iterator_tag,
typename C::difference_type,
typename C::pointer,
typename C::reference >
{
C * the_container;
typename C::size_type the_index;

indexing_iterator_base ( C * c,
typename C::size_type i )
: the_container ( c )
, the_index ( i )
{}

typename C::reference operator* ( void ) {
return ( the_container->operator[]( the_index ) );
}

typename C::pointer operator-> ( void ) {
return ( & this->operator*() );
}

};

template < typename Target, typename C >
struct indexing_iterator_base<Target,C,true> :
public std::iterator< std::random_access_iterator_tag,
typename C::difference_type,
typename C::const_pointer,
typename C::const_reference >
{

C const * the_container;
typename C::size_type the_index;

indexing_iterator_base ( C const * c,
typename C::size_type i )
: the_container ( c )
, the_index ( i )
{}

typename C::const_reference operator* ( void ) const {
return ( the_container->operator[]( the_index ) );
}

typename C::const_pointer operator-> ( void ) const {
return ( & this->operator*() );
}

};

template < typename IndexedCont,
bool is_const = const_qualifier<IndexedCont>::is_const >
struct indexing_iterator
: public indexing_iterator_base< indexing_iterator<IndexedCont,is_const>,
IndexedCont, is_const >
{

typedef IndexedCont container_type;
typedef typename container_type::size_type size_type;

private:

typedef indexing_iterator_base< indexing_iterator<IndexedCont,is_const>,
IndexedCont, is_const > my_base;

using typename my_base::reference;
using typename my_base::pointer;

public:

indexing_iterator ( typename reference_parameter< container_type, is_const
::type the_cont,
size_type the_index )
: my_base ( &the_cont, the_index )
{}

indexing_iterator & operator++ ( void ) {
++ my_base::the_index;
return ( *this );
}

indexing_iterator & operator-- ( void ) {
-- my_base::the_index;
return ( *this );
}

indexing_iterator operator++ ( int ) {
indexing_iterator result ( *this );
++ my_base::the_index;
return ( result );
}

indexing_iterator operator-- ( int ) {
indexing_iterator result ( *this );
-- my_base::the_index;
return ( result );
}

indexing_iterator operator+= ( typename my_base::difference_type dist ) {
my_base::the_index += dist;
return ( *this );
}

indexing_iterator operator-= ( typename my_base::difference_type dist ) {
my_base::the_index -= dist;
return ( *this );
}

indexing_iterator operator+ ( typename my_base::difference_type dist )
const {
return
( indexing_iterator
( &my_base::the_container, my_base::the_index + dist ) );
}

indexing_iterator operator- ( typename my_base::difference_type dist )
const {
return
( indexing_iterator
( &my_base::the_container, my_base::the_index - dist ) );
}

};

template < typename C, bool b >
typename indexing_iterator<C,b>::difference_type
operator- ( indexing_iterator<C,b> const & lhs,
indexing_iterator<C,b> const & rhs ) {
assert( lhs.the_container == rhs.the_container );
return ( lhs.the_index - rhs.the_index );
}

template < typename C, bool b >
bool operator== ( indexing_iterator<C,b> const & lhs,
indexing_iterator<C,b> const & rhs ) {
assert( lhs.the_container == rhs.the_container );
return ( lhs.the_index == rhs.the_index );
}

template < typename C, bool b >
bool operator!= ( indexing_iterator<C,b> const & lhs,
indexing_iterator<C,b> const & rhs ) {
assert( lhs.the_container == rhs.the_container );
return ( lhs.the_index != rhs.the_index );
}

template < typename C, bool b >
bool operator< ( indexing_iterator<C,b> const & lhs,
indexing_iterator<C,b> const & rhs ) {
assert( lhs.the_container == rhs.the_container );
return ( lhs.the_index < rhs.the_index );
}

template < typename C, bool b >
bool operator<= ( indexing_iterator<C,b> const & lhs,
indexing_iterator<C,b> const & rhs ) {
assert( lhs.the_container == rhs.the_container );
return ( lhs.the_index <= rhs.the_index );
}

template < typename C, bool b >
bool operator> ( indexing_iterator<C,b> const & lhs,
indexing_iterator<C,b> const & rhs ) {
assert( lhs.the_container == rhs.the_container );
return ( lhs.the_index > rhs.the_index );
}

template < typename C, bool b >
bool operator>= ( indexing_iterator<C,b> const & lhs,
indexing_iterator<C,b> const & rhs ) {
assert( lhs.the_container == rhs.the_container );
return ( lhs.the_index >= rhs.the_index );
}


struct point {

typedef float value_type;

typedef value_type & reference;
typedef value_type const & const_reference;
typedef value_type * pointer;
typedef value_type const * const_pointer;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;

value_type x, y, z;

point ( float x_, float y_, float z_ )
: x ( x_ )
, y ( y_ )
, z ( z_ )
{}

value_type const & operator[] ( std::size_t i ) const {
assert( i < 3 );
return ( (*this).*proxy() );
}

value_type & operator[] ( std::size_t i ) {
assert( i < 3 );
return ( (*this).*proxy() );
}

typedef indexing_iterator<point> iterator;

iterator begin ( void ) {
return ( iterator( *this, 0 ) );
}

iterator end ( void ) {
return ( iterator( *this, 3 ) );
}

typedef indexing_iterator<point const> const_iterator;

const_iterator begin ( void ) const {
return ( const_iterator( *this, 0 ) );
}

const_iterator end ( void ) const {
return ( const_iterator( *this, 3 ) );
}


private:

static
value_type point::* const * const proxy ( void ) {
static value_type point::* const dummy [3] =
{ &point::x, &point::y, &point::z };
return ( dummy );
}

};

namespace std {

template <>
struct less< point > {

bool operator() ( point const & lhs, point const & rhs ) {
return ( std::lexicographical_compare( lhs.begin(), lhs.end(),
rhs.begin(), rhs.end() ) );
}

};

} // namespace std

#include <iostream>
#include <iomanip>


int main ( void ) {
point p ( 1, 1, 1 );
point q ( 1, 1, 1.1 );
std::cout << std::boolalpha << std::less<point>()( p, q ) << '\n';
p.x = q[2];
std::cout << p.x << '\n';
}


Just kidding :)

However: hidden in the above code is yet another answer to your question.


Best

Kai-Uwe Bux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,201
Messages
2,571,048
Members
47,647
Latest member
NelleMacy9

Latest Threads

Top