Put User Defined Class into Union

E

Ed

Hi, guys,
A big rock blocks my way.

I know that to put a user defined class with copy constructor,
override operator method, etc, can not be placed into Union. But I
have to.

I am refactoring an old system with template feature. If there is no
way, that means I had to pay additional work to re-implementation.

I am wondering if there is some tricks to fix it?

Say, I have a simple template class:

template<typename P>
class Vector1
{
public:
P mValue;

public:
Vector1 (P);
Vector1 (const Vector1 vec_);

}

template<typename P>
class Vector3
{
public:
union
{
Vector1<P> p1;
Vector1<P> p2;
Vector1<P> p3;
}

}


Thanks!
 
E

Ed

* Ed:











Why do you want to access the same object via three different names?

Anyways, a union is not the answer for that.

Consider functions, references.

Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Sorry.
I give a improper sample code here. But the question is clear I think.
If I want to make a class as a member of union, how can I make it.

Change the sample code.

template<typename P>
class Vector1
{
public:
P mValue;

public:
Vector1 (P);
Vector1 (const Vector1 vec_);

}

template<typename P>
class Vector3
{
public:
union
{
Vector1<P> xyz[3];
struct
{
Vector1<P> x;
Vector1<P> y;
Vector1<P> z;
};
}
}


Thanks!
 
R

red floyd

Ed said:
* Ed:



Why do you want to access the same object via three different names?

Anyways, a union is not the answer for that.

Consider functions, references.

Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Sorry.
I give a improper sample code here. But the question is clear I think.
If I want to make a class as a member of union, how can I make it.

Change the sample code.

template<typename P>
class Vector1
{
public:
P mValue;

public:
Vector1 (P);
Vector1 (const Vector1 vec_);

}

template<typename P>
class Vector3
{
public:
union
{
Vector1<P> xyz[3];
struct
{
Vector1<P> x;
Vector1<P> y;
Vector1<P> z;
};
}
}

You can't. I believe you can only put a POD inside a union.
 
J

James Kanze

Ed wrote:

[...]
Yes. You need something like:

union SemanticValue
{
double d ;
int i ;
std::string s ;
} ;

With, obviously, some information elsewhere which tells you
which one (if any) is active.
If I want to make a class as a member of union, how can I
make it.
Change the sample code.
template<typename P>
class Vector1
{
public:
P mValue;
public:
Vector1 (P);
Vector1 (const Vector1 vec_);
}
template<typename P>
class Vector3
{
public:
union
{
Vector1<P> xyz[3];
struct
{
Vector1<P> x;
Vector1<P> y;
Vector1<P> z;
};
}
}

That looks bad. You do know that if you assign something to x,
you can no longer read xyz, and vice versa.
You can't. I believe you can only put a POD inside a union.

Practically. (I forget the exact list of restrictions, but
they're pretty close to making the object a POD.)

What you can do (at some cost in terms of programming effort) is
create a discriminated union. Something along the lines of:

class SemanticValue
{
public:
enum Type { typeDouble, typeInt, typeString } ;
explicit SemanticValue( double d ) ;
explicit SemanticValue( int i ) ;
explicit SemanticValue( std::string const& s ) ;
SemanticValue( SemanticValue const& other ) ;
~SemanticValue() ;
SemanticValue& operator=( SemanticValue const& other ) ;

Type type() const ;
operator double() const ;
operator int() const ;
operator std::string() const ;

private:
Type myType ;
union {
double d ;
int i ;
unsigned char s[ sizeof( std::string ) ] ;
// This supposes that std::string doesn't
// have stricter alignment requirements
// than double or int. Probably a safe
// bet.
} myData ;
} ;

SemanticValue::SemanticValue(
std::string const& s )
: myType( typeString )
{
new ( myData.s ) std::string( s ) ;
}

SemanticValue::~SemanticValue()
{
if ( myType == typeString ) {
reinterpret_cast< std::string* >( myData.s )
->std::string::~string() ;
}
}

and so on. (With manual type checking in the copy constructor
and assignment operator as well.)
 
E

Ed

Ed wrote:
[...]
I give a improper sample code here. But the question is clear I think..

Yes. You need something like:

union SemanticValue
{
double d ;
int i ;
std::string s ;
} ;

With, obviously, some information elsewhere which tells you
which one (if any) is active.


If I want to make a class as a member of union, how can I
make it.
Change the sample code.
template<typename P>
class Vector1
{
public:
P mValue;
public:
Vector1 (P);
Vector1 (const Vector1 vec_);
}
template<typename P>
class Vector3
{
public:
union
{
Vector1<P> xyz[3];
struct
{
Vector1<P> x;
Vector1<P> y;
Vector1<P> z;
};
}
}

That looks bad. You do know that if you assign something to x,
you can no longer read xyz, and vice versa.

If x was change, I think it will not impact the xyz reading, because
their addresses are the same.
Vector3<float> point;
point.x = 1.0f;
point.y = 1.0f;
point.z = 1.0f;

// If my thinking is right, the following assert should be true.
assert( point.x == point.xyz[0] );


You can't. I believe you can only put a POD inside a union.

Practically. (I forget the exact list of restrictions, but
they're pretty close to making the object a POD.)

What you can do (at some cost in terms of programming effort) is
create a discriminated union. Something along the lines of:

class SemanticValue
{
public:
enum Type { typeDouble, typeInt, typeString } ;
explicit SemanticValue( double d ) ;
explicit SemanticValue( int i ) ;
explicit SemanticValue( std::string const& s ) ;
SemanticValue( SemanticValue const& other ) ;
~SemanticValue() ;
SemanticValue& operator=( SemanticValue const& other ) ;

Type type() const ;
operator double() const ;
operator int() const ;
operator std::string() const ;

private:
Type myType ;
union {
double d ;
int i ;
unsigned char s[ sizeof( std::string ) ] ;
// This supposes that std::string doesn't
// have stricter alignment requirements
// than double or int. Probably a safe
// bet.
} myData ;
} ;

SemanticValue::SemanticValue(
std::string const& s )
: myType( typeString )
{
new ( myData.s ) std::string( s ) ;
}

SemanticValue::~SemanticValue()
{
if ( myType == typeString ) {
reinterpret_cast< std::string* >( myData.s )
->std::string::~string() ;
}
}

and so on. (With manual type checking in the copy constructor
and assignment operator as well.)

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Thanks for all of your suggestions. I get a lot.
 
J

James Kanze

template<typename P>
class Vector3
{
public:
union
{
Vector1<P> xyz[3];
struct
{
Vector1<P> x;
Vector1<P> y;
Vector1<P> z;
};
}
}
That looks bad. You do know that if you assign something to x,
you can no longer read xyz, and vice versa.
If x was change, I think it will not impact the xyz reading,
because their addresses are the same.

Maybe. Maybe not. The language makes no guarantees.
Vector3<float> point;
point.x = 1.0f;
point.y = 1.0f;
point.z = 1.0f;
// If my thinking is right, the following assert should be true.
assert( point.x == point.xyz[0] );

According to the language, that is undefined behavior. It might
work, or it might not. You can't even predict what might
happen.
 

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

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,227
Latest member
Daniella65

Latest Threads

Top