views:

96

answers:

1
#include <stdio.h>

struct B { int x,y; };

struct A : public B {
    // This whines about "copy assignment operator not allowed in union"
    //A& operator =(const A& a) { printf("A=A should do the exact same thing as A=B\n"); }
    A& operator =(const B& b) { printf("A = B\n"); }
};

union U {
    A a;
    B b;
};

int main(int argc, const char* argv[]) {
    U u1, u2;
    u1.a = u2.b;    // You can do this and it calls the operator =
    u1.a = (B)u2.a; // This works too
    u1.a = u2.a;    // This calls the default assignment operator >:@
}

Is there any workaround to be able to do that last line u1.a = u2.a with the exact same syntax, but have it call the operator = (don't care if it's =(B&) or =(A&)) instead of just copying data? Or are unrestricted unions (not supported even in Visual Studio 2010) the only option?

+3  A: 

C++ does not allow for a data member to be any type that has a full fledged constructor/destructor and/or copy constructor, or a non-trivial copy assignment operator.

This means that structure A can only have a default copy assignment operator (generated by the compiler) or not have it at all (declared as private with no definition).

You are confusing copy assignment operator vs assignment operator here. Copy assignment operator is a special case. In your example, A& operator =(const B & b) is not classified as a copy assignment operator, it is just an assignment operator and C++ does not restrict you from having it in the class being put into union. But when object is being assigned by copying, the copy assignment operator (that you have called a default assignment operator) will still be called.

There is no workaround to let you have a custom copy assignment operator. The first solution that comes to mind is to have this operator be a free function, but that is not allowed either.

So you have to come up with some alternative function instead of assignment. The closest thing would be to use some other operator, for example <<:

#include <stdio.h>

struct B { int x, y; };

struct A : B
{
    A& operator =(const B& b) { printf("A = B\n"); return *this; }
};

union U {
    A a;
    B b;
};

A & operator << (A & lhs, const B & rhs)
{
    printf ("A & operator << (const A & lhs, const B & rhs)\n");
    return lhs = rhs;
}

int
main ()
{
    U u1, u2;
    u1.a << u2.b;
    u1.a << u2.a;
}

This will output the following:

$ ./test 
A & operator << (const A & lhs, const B & rhs)
A = B
A & operator << (const A & lhs, const B & rhs)
A = B

Just in case, there are unrestricted unions in C++0x.

Hope it helps.

Vlad Lazarenko
Bummer. Declaring it as private also makes the compiler complain. Looks like I might be switching to gcc 4.6.
Chris
gcc 4.6 supports unrestricted unions if you enable C++0x support by passing `-std=c++0x` option to the `g++` command. Here is a list of C++0x features in gcc 4.6 - http://gcc.gnu.org/gcc-4.6/cxx0x_status.html
Vlad Lazarenko