I'm having a piece of code that compiles with msvc having language extensions enabled, but not with language extensions disabled. It breaks down to this minimal example:
class A
{
protected:
A(const A&);
A& operator=(const A&);
A(A&&);
A& operator=(A&&);
};
class B : public A
{
public:
B& operator=(B&&);
};
inline B& B::operator=(B&&) = default; // error C2248
With the error message being
C2248 'A::A': cannot access protected member declared in class 'A'
in line 14 where the move assignment operator is defined. Interestingly, the following code compiles just fine:
class A
{
protected:
A(const A&);
A& operator=(const A&);
A(A&&);
A& operator=(A&&);
};
class B : public A
{
public:
B& operator=(B&&) = default;
};
Also interestingly, this only happens with the move-assignment-operator. The copy-assignment-operator, as well as the copy- and move-constructor (but not the move-assignment-operator) of B can be defined outside the class definition, inline, and default and the code will compile.
What am I doing wrong?
In the C++ programming language, the move assignment operator = is used for transferring a temporary object to an existing object. The move assignment operator, like most C++ operators, can be overloaded. Like the copy assignment operator it is a special member function.
Move assignment operators typically "steal" the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors, TCP sockets, I/O streams, running threads, etc.), rather than make copies of them, and leave the argument in some valid but otherwise indeterminate state.
If a copy constructor, copy-assignment operator, move constructor, move-assignment operator, or destructor is explicitly declared, then: No move constructor is automatically generated. No move-assignment operator is automatically generated.
This operator is called when an already initialized object is assigned a new value from another existing object. It creates a separate memory block for the new object. It does not create a separate memory block or new memory space. It is an overloaded constructor.
What am I doing wrong?
Nothing.
An explicitly defaulted definition would be exactly the same one a compiler would produce. In this case, it would move assign all bases and members. That requires the move assignment operators of those bases and members to be accessible to the one your are defaulting, of course. And yours is accessible, on account of being protected.
This is a MSVC++ bug. Try updating to a later version if you can.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With