casting from void*

Discussion in 'C++' started by Cristiano, Sep 11, 2012.

  1. Cristiano

    Cristiano Guest

    I have a structure like this (the actual structure is much bigger):

    struct Generic {
    char ID[6];
    std::vector <obj1_info> info1;
    std::vector <obj2_info> info2;
    std::vector <obj3_info> info3;
    std::vector <obj4_info> info4;
    };

    I use it to store 4 types of objects.
    Each object needs its own std::vector to store informations related to
    that object.

    To avoid wasting of space I though to use a void * instead:

    struct Generic {
    char ID[6];
    void *ptr;
    };

    Not a good idea, I know.
    First question: does anybody have a good idea?

    I allocate the right std::vector using:

    ptr= new std::vector<obj1_info>;
    obj1_info x; x.var= 0;
    ((std::vector<obj1_info>*)ptr)->push_back(x);

    but when I try to read x (using some horrible casting) I get errors
    (violation access, wrong result).
    How should I cast the ptr pointer?

    Thanks
    Cristiano
     
    Cristiano, Sep 11, 2012
    #1
    1. Advertising

  2. On 9/11/2012 7:15 AM, Cristiano wrote:
    > I have a structure like this (the actual structure is much bigger):
    >
    > struct Generic {
    > char ID[6];
    > std::vector <obj1_info> info1;
    > std::vector <obj2_info> info2;
    > std::vector <obj3_info> info3;
    > std::vector <obj4_info> info4;
    > };
    >
    > I use it to store 4 types of objects.
    > Each object needs its own std::vector to store informations related to
    > that object.
    >
    > To avoid wasting of space I though to use a void * instead:
    >
    > struct Generic {
    > char ID[6];
    > void *ptr;
    > };
    >
    > Not a good idea, I know.
    > First question: does anybody have a good idea?


    Use a union, that's what they are for.

    struct Generic {
    char ID[6];
    union {
    std::vector<obj1_info> info1;
    std::vector<obj2_info> info2;
    ...
    } u;
    };

    That way all of your 'infoN' objects will share the memory, and since
    they can never co-exist (IOW, it's exclusive use of memory) and you can
    ensure that what you put into the 'u' is what you get out (IOW, never
    try to write 'u.info1' and then read 'u.info2'), you're going to be OK.

    > I allocate the right std::vector using:
    >
    > ptr= new std::vector<obj1_info>;
    > obj1_info x; x.var= 0;
    > ((std::vector<obj1_info>*)ptr)->push_back(x);
    >
    > but when I try to read x (using some horrible casting) I get errors
    > (violation access, wrong result).
    > How should I cast the ptr pointer?


    Don't.

    With a union you will need to make sure to clear the currently allocated
    vector just before you put the other one in (if ever), but that's the
    only hassle.

    Now, if you still don't want to use a union, I'd recommend writing
    accessor methods for 'Generic'. Something like

    struct Generic {
    ... // whatever data layout
    template<class D> Generic(const D& primer) {
    // set the ID somehow
    std::vector<D> *pV = new std::vector<D>();
    pV->push_back(primer);
    ptr = pV;
    }
    };

    and use it similarly to

    obj1_info x; // and whatever else
    ..
    Generic gen(x); // will invoke the right constructor

    You will also need accessors for the elements of those vectors that will
    check the ID, but for those you will need to supply the ID. Do you have
    the interface in mind?

    As you probably already understand, I *strongly* recommend *against*
    keeping your 'Generic' type the "dumb data". Give it some intelligence
    by supplying proper member functions for accessing the data. You will
    thank yourself later.

    Good luck!

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 11, 2012
    #2
    1. Advertising

  3. Cristiano

    Cristiano Guest

    On 11/09/2012 14:59, Victor Bazarov wrote:
    > On 9/11/2012 7:15 AM, Cristiano wrote:
    >> I have a structure like this (the actual structure is much bigger):
    >>
    >> struct Generic {
    >> char ID[6];
    >> std::vector <obj1_info> info1;
    >> std::vector <obj2_info> info2;
    >> std::vector <obj3_info> info3;
    >> std::vector <obj4_info> info4;
    >> };
    >>
    >> I use it to store 4 types of objects.
    >> Each object needs its own std::vector to store informations related to
    >> that object.
    >>
    >> To avoid wasting of space I though to use a void * instead:
    >>
    >> struct Generic {
    >> char ID[6];
    >> void *ptr;
    >> };
    >>
    >> Not a good idea, I know.
    >> First question: does anybody have a good idea?

    >
    > Use a union, that's what they are for.
    >
    > struct Generic {
    > char ID[6];
    > union {
    > std::vector<obj1_info> info1;
    > std::vector<obj2_info> info2;
    > ...
    > } u;
    > };


    I like that idea, but I get the compiler error that a union member
    cannot have a copy ctor:
    http://msdn.microsoft.com/en-us/library/bd149yt8(v=vs.80).aspx

    > Now, if you still don't want to use a union, I'd recommend writing
    > accessor methods for 'Generic'. Something like
    >
    > struct Generic {
    > ... // whatever data layout
    > template<class D> Generic(const D& primer) {
    > // set the ID somehow
    > std::vector<D> *pV = new std::vector<D>();
    > pV->push_back(primer);
    > ptr = pV;
    > }
    > };
    >
    > and use it similarly to
    >
    > obj1_info x; // and whatever else
    > ..
    > Generic gen(x); // will invoke the right constructor
    >
    > You will also need accessors for the elements of those vectors that will
    > check the ID, but for those you will need to supply the ID. Do you have
    > the interface in mind?


    No, I'm still building the structures I need.
    Instead of writing all that code, I guess it's better to waste some
    memory, but I need to check what happens without the union.

    > As you probably already understand, I *strongly* recommend *against*
    > keeping your 'Generic' type the "dumb data". Give it some intelligence
    > by supplying proper member functions for accessing the data. You will
    > thank yourself later.
    >
    > Good luck!


    Thank you
    Cristiano
     
    Cristiano, Sep 11, 2012
    #3
  4. Cristiano

    Guest

    On Tuesday, September 11, 2012 6:15:19 AM UTC-5, Cristiano wrote:
    > I have a structure like this (the actual structure is much bigger):
    >
    >
    >
    > struct Generic {
    >
    > char ID[6];
    >
    > std::vector <obj1_info> info1;
    >
    > std::vector <obj2_info> info2;
    >
    > std::vector <obj3_info> info3;
    >
    > std::vector <obj4_info> info4;
    >
    > };
    >
    >
    >
    > I use it to store 4 types of objects.
    >
    > Each object needs its own std::vector to store informations related to
    >
    > that object.
    >
    >
    >
    > To avoid wasting of space I though to use a void * instead:
    >
    >
    >
    > struct Generic {
    >
    > char ID[6];
    >
    > void *ptr;
    >
    > };
    >
    >
    >
    > Not a good idea, I know.
    >
    > First question: does anybody have a good idea?


    You can create an abstract base class that's conceptually an interface and have all the info's implement it:

    class ObjectInfo
    {
    public:
    virtual Xyz GetXyz() const = 0;
    virtual Zyx GetZyx() const = 0;
    };

    class Object1Info : public ObjectInfo { ... };
    class Object2Info : public ObjectInfo { ... };

    And the vector in Generic will store ObjectInfo pointers:

    struct Generic
    {
    char ID[6];
    std::vector<ObjectInfo*> info; // or maybe vector<shared_ptr<ObjectInfo>>
    };

    Then you can add any kind of ObjectInfo to the vector:

    Object1Info* x = new Object1Info();
    x->var = 0;
    info.push_back(x);

    Although this saves space (for the vectors), it introduces more dynamic allocations, and I'm not sure what's the space overhead of the virtual methods.
     
    , Sep 11, 2012
    #4
  5. On 9/11/2012 9:53 AM, Cristiano wrote:
    > On 11/09/2012 14:59, Victor Bazarov wrote:
    >> On 9/11/2012 7:15 AM, Cristiano wrote:
    >>> I have a structure like this (the actual structure is much bigger):
    >>>
    >>> struct Generic {
    >>> char ID[6];
    >>> std::vector <obj1_info> info1;
    >>> std::vector <obj2_info> info2;
    >>> std::vector <obj3_info> info3;
    >>> std::vector <obj4_info> info4;
    >>> };
    >>>
    >>> I use it to store 4 types of objects.
    >>> Each object needs its own std::vector to store informations related to
    >>> that object.
    >>>
    >>> To avoid wasting of space I though to use a void * instead:
    >>>
    >>> struct Generic {
    >>> char ID[6];
    >>> void *ptr;
    >>> };
    >>>
    >>> Not a good idea, I know.
    >>> First question: does anybody have a good idea?

    >>
    >> Use a union, that's what they are for.
    >>
    >> struct Generic {
    >> char ID[6];
    >> union {
    >> std::vector<obj1_info> info1;
    >> std::vector<obj2_info> info2;
    >> ...
    >> } u;
    >> };

    >
    > I like that idea, but I get the compiler error that a union member
    > cannot have a copy ctor:
    > http://msdn.microsoft.com/en-us/library/bd149yt8(v=vs.80).aspx


    OK, I didn't think of that. Then perhaps unions are not such a great
    idea, although you could still use a union if instead of straight
    vectors, you use pointers to vectors.

    >
    >> Now, if you still don't want to use a union, I'd recommend writing
    >> accessor methods for 'Generic'. Something like
    >>
    >> struct Generic {
    >> ... // whatever data layout
    >> template<class D> Generic(const D& primer) {
    >> // set the ID somehow
    >> std::vector<D> *pV = new std::vector<D>();
    >> pV->push_back(primer);
    >> ptr = pV;
    >> }
    >> };
    >>
    >> and use it similarly to
    >>
    >> obj1_info x; // and whatever else
    >> ..
    >> Generic gen(x); // will invoke the right constructor
    >>
    >> You will also need accessors for the elements of those vectors that will
    >> check the ID, but for those you will need to supply the ID. Do you have
    >> the interface in mind?

    >
    > No, I'm still building the structures I need.
    > Instead of writing all that code, I guess it's better to waste some
    > memory, but I need to check what happens without the union.


    Also, consider writing your 'Generic' actually generically (as a template):

    template<class D> struct MyStuff {
    char ID[6];
    std::vector<D> obj_info;
    };

    Perhaps you need to come up with a clear interface to your class instead
    of its inner workings first.

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 11, 2012
    #5
  6. Cristiano

    Melzzzzz Guest

    On Tue, 11 Sep 2012 11:50:12 -0400
    Victor Bazarov <> wrote:

    > On 9/11/2012 9:53 AM, Cristiano wrote:
    > > On 11/09/2012 14:59, Victor Bazarov wrote:
    > >> On 9/11/2012 7:15 AM, Cristiano wrote:
    > >>> I have a structure like this (the actual structure is much
    > >>> bigger):
    > >>>
    > >>> struct Generic {
    > >>> char ID[6];
    > >>> std::vector <obj1_info> info1;
    > >>> std::vector <obj2_info> info2;
    > >>> std::vector <obj3_info> info3;
    > >>> std::vector <obj4_info> info4;
    > >>> };
    > >>>
    > >>> I use it to store 4 types of objects.
    > >>> Each object needs its own std::vector to store informations
    > >>> related to that object.
    > >>>
    > >>> To avoid wasting of space I though to use a void * instead:
    > >>>
    > >>> struct Generic {
    > >>> char ID[6];
    > >>> void *ptr;
    > >>> };
    > >>>
    > >>> Not a good idea, I know.
    > >>> First question: does anybody have a good idea?
    > >>
    > >> Use a union, that's what they are for.
    > >>
    > >> struct Generic {
    > >> char ID[6];
    > >> union {
    > >> std::vector<obj1_info> info1;
    > >> std::vector<obj2_info> info2;
    > >> ...
    > >> } u;
    > >> };

    > >
    > > I like that idea, but I get the compiler error that a union member
    > > cannot have a copy ctor:
    > > http://msdn.microsoft.com/en-us/library/bd149yt8(v=vs.80).aspx

    >
    > OK, I didn't think of that. Then perhaps unions are not such a great
    > idea, although you could still use a union if instead of straight
    > vectors, you use pointers to vectors.


    In c++11, I think, unions with classes that have constructors are
    allowed.
     
    Melzzzzz, Sep 11, 2012
    #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. Ollej Reemt
    Replies:
    7
    Views:
    568
    Jack Klein
    Apr 22, 2005
  2. Stig Brautaset

    `void **' revisited: void *pop(void **root)

    Stig Brautaset, Oct 25, 2003, in forum: C Programming
    Replies:
    15
    Views:
    814
    The Real OS/2 Guy
    Oct 28, 2003
  3. David M. Wilson
    Replies:
    8
    Views:
    498
    Ben Pfaff
    Jan 7, 2004
  4. Replies:
    5
    Views:
    851
    S.Tobias
    Jul 22, 2005
  5. Replies:
    1
    Views:
    420
    Victor Bazarov
    May 23, 2007
Loading...

Share This Page