Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ default move assignment cannot access protected base member

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?

like image 882
crudeyDrawn Avatar asked May 03 '18 08:05

crudeyDrawn


People also ask

How does move assignment work C++?

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.

What does a move assignment operator do?

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.

Are move constructor automatically generated?

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.

When assignment operator is called in C++?

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.


1 Answers

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.

like image 143
StoryTeller - Unslander Monica Avatar answered Sep 19 '22 16:09

StoryTeller - Unslander Monica