views:

344

answers:

6

I am working on a project with a library and I must work with unions. Specifically I am working with SDL and the SDL_Event union. I need to make copies of the SDL_Events, and I could find no good information on overloading assignment operators with unions.

Provided that I can overload the assignment operator, should I manually sift through the union members and copy the pertinent members or can I simply come some members (this seems dangerous to me), or maybe just use memcpy() (this seems simple and fast, but slightly dangerous)?

If I can't overload operators what would my best options be from there? I guess I could make new copies and pass around a bunch of pointers, but in this situation I would prefer not to do that.

Any ideas welcome!

EDIT: as requested Errors messages, and incidentally I think I have learned something...

physworld.cpp:325: error: no match for ‘operator=’ in ‘CurrentEvent = ((physworld*)this)->physworld::SDL_UserInputEvents.std::queue<_Tp, _Sequence>::pop [with _Tp = SDL_Event, _Sequence = std::deque<SDL_Event, std::allocator<SDL_Event> >]()’ /usr/include/SDL/SDL_events.h:220: note: candidates are: SDL_Event& SDL_Event::operator=(const SDL_Event&)

EDIT2: This was so stupid... I thought that Deqeues pop() member returned the item removed. I thought the code was so simple that it couldn't directly be my code, but that turned out to be wrong.

my code looked like:

 for(SDL_Event CurrentEvent; !DequeueOfSDLEvents.empty(); CurrentEvent = DequeueOfSDLEvents.pop() )
 {
   //Do stuff
 }

So if nothing else I will learn to look more closely at member functions of containers I haven't used recently. Thanks for explaining assignment worked by default, otherwise It would have taken longer to find this.

+3  A: 

Since unions are (by definition) only allowed to contain PODs, then you can safely use memcpy to copy them.

Dean Harding
POD? Plain Old Data, as in not classes? Oh and is there a way to overload the = operator?
Sqeaky
An union may contain non-PODs (i think it's legal to have members contain private members) and may declare an own copy constructor (just its members may not have an own copy constructor). So memcpy an arbitrary union may not be safe and depends. I think most unions are such that memcpy is perfectly safe though.
Johannes Schaub - litb
+2  A: 

In a union, the elements all occupy the same memory, like they sit on top of each other. If you write to another element of a union, it overwrites the others.

As such, copying element by element is a waste of time. You could copy the largest element only, but then you would have to know which one that is (not every element of the union has to be the same size) Best thing to do is to just memcpy the union.

But its even simpler than that, you should be able to just do an assignment, and the compiler, realizing you are copying a struct or union, will do the "memcpy" for you implicitly.

Matthias Wandel
I tried assignment, and it was not going to compile, I guess that some member is non-copyable, maybe?
Sqeaky
@Sqeaky show us the error message. We can't guess what the problem is. Looking over the docs nothing in SDL_Event seems like it should be problematic to copy.
Logan Capaldo
A: 

Looks like a typical use case of boost::variant cheers, AR

[Edit] Why not appropriate?

#define BOOST_VARIANT_LIMIT_TYPES 14
typedef boost::variant<Uint8, SDL_ActiveEvent, SDL_KeyboardEvent, ...,SDL_SysWMEvent> MyEvent;
Alain Rist
Oh I wish, that seems neat, but not directly appropriate, I am stuck with SDL_Events - http://www.libsdl.org/cgi/docwiki.cgi/SDL_Event
Sqeaky
+1  A: 

I may be mistaken, but don't unions support assignment out of the box?

#include <cassert>

union X
{
    int a;
    double b;
};

int main()
{
    X x;
    x.a = 10;
    X y;
    y = x;
    assert(y.a == x.a);
}

It also appears you can also overload operator= for it as usual, but what exactly would you want to be different than in normal default assignment?

UncleBens
This code works as expected, but I tried assignment, and it is not going to compile, I guess that some member is non-copyable, maybe?
Sqeaky
A: 

Generally speaking, you can just use the compiler-generated assignment operator. The only exception I can think of would be if you had a union that could contain a pointer, and you wanted to implement a deep copy for that pointer. To handle that well, you'd have to make it a discriminated union so you could determine the type and copy the pointer appropriately. As long as you don't have remote ownership, however, the compiler-generated assignment (and copy ctor) should work fine.

Jerry Coffin
A: 

You don't need to do anything special. In my opinion overloading or adding operators would only add complexity. The SDL_event is a simple unsigned char.

SDL_Events a;
SDL_Events b;

a = b;  // this will copy the value
Dan