cuvidk cuvidk - 1 month ago 10
C++ Question

Does delete/default keywords mark the corresponding method as user defined?

I have the following code:

#include <iostream>

class B{
public:
//this should all be generated by default but
//throwing them in here just to be sure
B() = default;
B(const B& b) = default;
B& operator=(const B& b) = default;
B(B&& b) = default;
B& operator=(B&& b) = default;
};

class A {
public:
A(B x) : x_(x) {}
A(const A& a) = delete;
A& operator=(const A& a) = delete;
//move operations should be generated by compiler?
private:
B x_;
};

int main() {
A a = A(B());
}


I'm expecting this to compile and an
A
to be created using it's move constructor, but instead this fails with the following message:


error: use of deleted function ‘A::A(const A&)’
A a = A(B());
note: declared here
A(const A& a) = delete;


Of course adding the move operations and marking them with the default keywords eliminates the problem. Should I assume that the move operations were not generated by the compiler, why is that? Does delete keyword mark the methods as user-implemented so no move operations are generated? Why is the copy constructor prefered instead? I'm using gcc to compile.

Answer

If you provide implementation of copy constructor/operator=, move operations are no longer generated by default. If you want them, you need to explicitly tell that you do.

As per cppreference:

If no user-defined move constructors are provided for a class type (struct, class, or union), and all of the following is true:

  • there are no user-declared copy constructors;
  • there are no user-declared copy assignment operators;
  • there are no user-declared move assignment operators;
  • there are no user-declared destructors;

then the compiler will declare a move constructor as a non-explicit inline public member of its class with the signature T::T(T&&).

Here's a helpful chart for this kind of situation:

enter image description here attribution