Put User Defined Class into Union

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ed

    Put User Defined Class into Union

    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<typena me P>
    class Vector1
    {
    public:
    P mValue;

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

    }

    template<typena me P>
    class Vector3
    {
    public:
    union
    {
    Vector1<Pp1;
    Vector1<Pp2;
    Vector1<Pp3;
    }

    }


    Thanks!
  • James Kanze

    #2
    Re: Put User Defined Class into Union

    On Aug 12, 4:45 am, red floyd <no.spam.h...@e xample.comwrote :
    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<typena me P>
    class Vector1
    {
    public:
    P mValue;
    public:
    Vector1 (P);
    Vector1 (const Vector1 vec_);
    }
    template<typena me P>
    class Vector3
    {
    public:
    union
    {
    Vector1<Pxyz[3];
    struct
    {
    Vector1<Px;
    Vector1<Py;
    Vector1<Pz;
    };
    }
    }
    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_cas t< 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:james.kan ze@gmail.com
    Conseils en informatique orientée objet/
    Beratung in objektorientier ter Datenverarbeitu ng
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

    Comment

    • Ed

      #3
      Re: Put User Defined Class into Union

      On Aug 12, 5:30 pm, James Kanze <james.ka...@gm ail.comwrote:
      On Aug 12, 4:45 am, red floyd <no.spam.h...@e xample.comwrote :
      >
      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<typena me P>
      class Vector1
      {
      public:
      P mValue;
      public:
      Vector1 (P);
      Vector1 (const Vector1 vec_);
      }
      template<typena me P>
      class Vector3
      {
      public:
      union
      {
      Vector1<Pxyz[3];
      struct
      {
      Vector1<Px;
      Vector1<Py;
      Vector1<Pz;
      };
      }
      }
      >
      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<floatpo int;
      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_cas t< 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:james.ka. ..@gmail.com
      Conseils en informatique orientée objet/
      Beratung in objektorientier ter Datenverarbeitu ng
      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.

      Comment

      • James Kanze

        #4
        Re: Put User Defined Class into Union

        On Aug 13, 9:20 am, Ed <seah...@gmail. comwrote:
        On Aug 12, 5:30 pm, James Kanze <james.ka...@gm ail.comwrote:
        template<typena me P>
        class Vector3
        {
        public:
        union
        {
        Vector1<Pxyz[3];
        struct
        {
        Vector1<Px;
        Vector1<Py;
        Vector1<Pz;
        };
        }
        }
        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<floatpo int;
        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:james.kan ze@gmail.com
        Conseils en informatique orientée objet/
        Beratung in objektorientier ter Datenverarbeitu ng
        9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

        Comment

        Working...