3

I have a class which has a union as one of its members. I also am a big fan of the copy/swap idiom. It occurred to me that there doesn't appear to be any correct (in the sense of the standard) to swap unions!

Here's the best that I could come up with:

char tmp[sizeof(U)];
memcpy(tmp, &u1, sizeof(U));
memcpy(&u1, &u2, sizeof(U));
memcpy(&u2, tmp, sizeof(U));

Since unions (at least in c++03) require that all members be POD, I don't see why this wouldn't work. But it just doesn't feel right. Is there a more correct way to swap unions? It seems almost like something that was overlooked.

What do you guys think?

EDIT:

OK, I feel kinda dumb after seeing the solutions given :-). I wrote off traditional solutions like std::swap and assignment because when I first wrote the code, the union was an anonymous union. In the current version of the code, the union is no longer anonymous and traditional solutions seem to work just fine. Thanks.

Evan Teran
  • 87,561
  • 32
  • 179
  • 238

2 Answers2

7

Simply:

#include <algorithm>
std::swap(u1, u2);

Unions are both copy-constructible and assignable, so there is no problem.

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • I originally had that, but I think vc++2008 barfed on it. I'll look into it again. – Evan Teran Apr 13 '11 at 16:17
  • Come to think about it, previously the union was anonymous (it no longer is), perhaps vc++ just didn't like swapping anonymous unions? – Evan Teran Apr 13 '11 at 16:19
  • 3
    @Evan Teran: §14.3.1 [temp.arg.type]/2 *A local type, a type with no linkage, an **unnamed type** or a type compounded from any of these types **shall not be** used as **a template-argument** for a template type-parameter.* So basically yes, you cannot use an *unnamed* union as a type argument to a template, and `std::swap` is a template. – David Rodríguez - dribeas Apr 13 '11 at 17:08
3

Why not use classical swap solution?

U u1, u2;
// ...
U t = u1;
u1 = u2;
u2 = t;

This is expected to work since assignment of unions is valid.

andrew_d
  • 83
  • 5