Put User Defined Class into Union

Discussion in 'C++' started by Ed, Aug 11, 2008.

  1. Ed

    Ed Guest

    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!
    Ed, Aug 11, 2008
    #1
    1. Advertising

  2. Ed

    Ed Guest

    On Aug 11, 4:29 pm, "Alf P. Steinbach" <> wrote:
    > * 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;
    > > }

    >
    > > }

    >
    > 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!
    Ed, Aug 12, 2008
    #2
    1. Advertising

  3. Ed

    red floyd Guest

    Ed wrote:
    > On Aug 11, 4:29 pm, "Alf P. Steinbach" <> wrote:
    >> * 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;
    >>> }
    >>> }

    >> 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.
    red floyd, Aug 12, 2008
    #3
  4. Ed

    James Kanze Guest

    On Aug 12, 4:45 am, red floyd <> wrote:
    > 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.

    > 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:
    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
    James Kanze, Aug 12, 2008
    #4
  5. Ed

    Ed Guest

    On Aug 12, 5:30 pm, James Kanze <> wrote:
    > On Aug 12, 4:45 am, red floyd <> wrote:
    >
    > > 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:
    > 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.
    Ed, Aug 13, 2008
    #5
  6. Ed

    James Kanze Guest

    On Aug 13, 9:20 am, Ed <> wrote:
    > On Aug 12, 5:30 pm, James Kanze <> wrote:
    > > > > 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.

    --
    James Kanze (GABI Software) email:
    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
    James Kanze, Aug 13, 2008
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Matt Garman
    Replies:
    1
    Views:
    651
    Matt Garman
    Apr 25, 2004
  2. Peter Dunker

    union in struct without union name

    Peter Dunker, Apr 26, 2004, in forum: C Programming
    Replies:
    2
    Views:
    853
    Chris Torek
    Apr 26, 2004
  3. Oodini
    Replies:
    1
    Views:
    1,750
    Keith Thompson
    Sep 27, 2005
  4. Replies:
    1
    Views:
    481
    Sion Arrowsmith
    Jul 10, 2008
  5. Galileo
    Replies:
    0
    Views:
    97
    Galileo
    Oct 21, 2003
Loading...

Share This Page