Repeating error message:
main.cpp(56): error C2280: 'Rect &Rect::operator =(const Rect &)': attempting to reference a deleted function
This is pretty clear: the operator= member function with the const Rect & parameter was delete d, but your code is trying to call it on the line test = Rect(); .
Then you say:
The compiler is trying to tell me that the Rect copy constructor is a remote function
However, you are not reading the error correctly. The error is associated with the operator = function, which is called the copy assignment operator. This is another constructor copy function that will look like Rect::Rect(const Rect &) .
You say you tried to add:
Rect& operator=(const Rect&) = default;
However, this does not matter. The function generated by the compiler operator= delete d, because the compiler cannot generate one (explanation of this below); entry = default; doesn't change that. You should actually write your own body for operator= , which performs the actions you want to perform when the assignment happens.
In standard C ++, it is not allowed to have an anonymous structure, not to mention an anonymous structure inside an anonymous union. So you are truly on your own. The rules your compiler uses regarding operator= , copy constructor, etc., are not covered by any Standard.
A version of your Rect that compiles to the C standard might look like this:
class Rect { public: struct S1 { Vector p1, p2; S1(Vector p1, Vector p2): p1(p1), p2(p2) {} }; struct S2 { float p1x, p1y, p2x, p2y; }; union { struct S1 s1; struct S2 s2; }; Rect() : s1({0, 0}, {0, 0}) {} Rect(Vector p1, Vector p2) : s1(p1, p2) {} };
So far so good. For this class, the implicitly declared operator= is defined as remote. To understand why we first need to consider implicitly declared special functions for anonymous union, since the behavior of an implicitly declared function for a class depends on the behavior of the same operation for each of its members.
The corresponding rule for combining is C ++ 14 [class.union] / 1:
If any non-static join data member has a non-trivial default constructor, copy constructor, move constructor, copy assignment operator, redirection assignment operator or destructor, the corresponding join member function must be provided by the user or it will implicitly delete d for the join.
Vector has a non-trivial operator= , because you write your own body for it. Therefore, S1 has a non-trivial operator= , because it has a member with a non-trivial operator= , and therefore, according to the above quote, the implicitly declared operator= for the union is delete d.
Note that there is no error in the copy constructor: Vector has a trivial copy constructor, so the union too.
To fix this error, you can do one of two things:
- Change
Vector::operator= to trivial, either by completely deleting your definition, or by making it = default; - Write
operator= for the Rect class
Now, how would you write your own operator= ? You do s1 = other.s1; , or you do s2 = other.s2; ? The compiler cannot know this on its own, which is the reason that the implicitly declared operator= will be deleted.
Now it seems to you that you are ignoring (accidentally or intentionally) the rule about active members in C ++:
In a union, no more than one non-static data element can be active at any time.
This means that if S1 is the last set of elements, you need to do s1 = other.s1; . Or, if s2 is the last set of members, you will need to do s2 = other.s2; .
The copy constructor does not encounter this problem because it is trivial: the compiler can generate a bit-muddy copy, and this will correctly implement the copy no matter which member was active. But since your operator= nontrivial, this is not possible.
For example, imagine if you really had a union of std::string and std::vector - a bitwise copy does not work for any of them, and you need to know which one is active in order to execute the copy.
Repeating: In standard C ++, it is not allowed to read a member of a union other than the last one written in . You cannot use unions for aliases. C ++ has tools in another language to achieve what you can do in C by merging with union, see here for further discussion .
Based on the selection of members for your anonymous structures, I suspect that this is what you intended to do. If you really want to continue this approach, relying on your compiler that implements union pseudo-reduction as a non-standard extension, then my advice will be to use the standard operator= for your Vector class.