1

As per this post, which says that[emphasise mine]:

The move assignment operator is auto-generated if there is no user-declared copy constructor, copy assignment operator or destructor, and if the generated move assignment operator is valid (e.g. if it wouldn't need to assign constant members) (§12.8/21).

Does an inherited destructor count? I mean, say I've got a base class with an empty virtual destructor. Does it prevent creation of move constructors in subclasses?

Evg
  • 25,259
  • 5
  • 41
  • 83
John
  • 2,963
  • 11
  • 33

2 Answers2

1

The compiler will generate the move constructors for you:

#include <iostream>
#include <memory>
#include <utility>

struct Foo {
    virtual ~Foo() {}
};

struct Bar : public Foo {
    Bar() : pi(new int(5)) {};

    std::unique_ptr<int> pi;
};

int main()
{
    Bar b;
    std::cout << b.pi.get() << std::endl;
    Bar c = std::move(b);
    std::cout << b.pi.get() << std::endl;
    std::cout << c.pi.get() << std::endl;
}

which (on a given run), output:

0x1b65e70
0
0x1b65e70

Try it online!

If the compiler had not generated the move constructor, c could not have been constructed (since by using std::unique_ptr as a member, implicit copy is not allowed), and clearly the ownership over the pointer was transferred properly. The code was compiled under GCC with warnings maxed out in -std=c++17 mode, with no issues.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
0

You can tell if a member function is user-declared by looking at the class definition. If you see the function, then it is user-declared.

For example:

class Derived : public Base {
   ~Derived() = default; // <-- see this? user-declared destructor
};

In contrast to:

class Derived : public Base {
   // <-- see a destructor here? No. So not a user-declared destructor
};

The compiler generates the same destructor body in both cases, but the former example has a user-declared destructor, while the latter has an auto-generated destructor. The user-declared destructor is compiler-generated in this case, but it is generated at the user's request, so it is not auto-generated.

For "user-declared", it does not matter what's going on in the base class. If you see the destructor listed, as in the first example, then the compiler will not auto-generate move assignment or move construction. If you do not see the destructor listed, as in the second example, then the other criteria for auto-generation need to be checked.

The base class' influence on which members are auto-generated is restricted to the "is valid" criterion.

JaMiT
  • 14,422
  • 4
  • 15
  • 31
  • The most important phrase in the answer is "it does not matter what's going on in the base class". The base class may or may not have a move ctor, but if it has a copy ctor available, the derived will use it to move itself. – n. m. could be an AI May 04 '22 at 07:53