3

The following class hierarchy will cause a [-Wvirtual-move-assign] warning in GCC if a move assign is invoked for an instance of B.

struct A {

    std::vector<int> v; // I believe this can be a variable of any class
                        // that implements a move assignment.

};

struct B : public virtual A {};

Despite the warning, in this particular class hierarchy there appears at first to be no danger because A is not accessible through multiple paths, but someone could inherit from B and some other class C that inherits virtually from A and the problem arises. So lets assume we want to fix the issue correctly in case that happens.

According to this question, the correct way to solve this issue is to implement a move assignment operator for B that can detect that the virtual base class A is in the moved-from state and omit a second movement, however it does not provide an example of how this would be done correctly. Please provide an example of the implementation of move assignment for class B that correctly handles the duplicate move.

Should the move constructor also be implemented to avoid duplicate moves or does the default move constructor not suffer from the same problem? Please also provide an example if applicable.

Adam Sperry
  • 283
  • 1
  • 9
  • Does [Warning: defaulted move assignment operator of X will move assign virtual base class Y multiple times](https://stackoverflow.com/questions/34554612/warning-defaulted-move-assignment-operator-of-x-will-move-assign-virtual-base-c) provide insight? (Maybe not exactly a duplicate?) – JaMiT Apr 10 '20 at 21:41
  • Well, if multithreading is not a concern, just add a `bool i_have_been_moved_from_already_so_go_away;` class member, and implement it accordingly? – Sam Varshavchik Apr 10 '20 at 21:47
  • @JaMiT It certainly answers my question about the move constructor and offers a lot of insight. The one part I'm left not understanding is whether the move assignment operator for a class is responsible for moving data for the entire hierarchy above it or whether it is more like implementing a constructor in which you are typically responsible for the current class (assuming there is nothing in the initializer list) and initializing base classes is left to their respective constructors – Adam Sperry Apr 11 '20 at 00:19
  • @JaMiT I have only ever seen examples of move assignment operators for classes that are not in a hierarchy – Adam Sperry Apr 11 '20 at 00:21
  • @AdamSperry: All special member functions are responsible for calling the corresponding base class functions—it’s only default constructors and destructors where that’s automatic in a useful way. Solving this problem without cooperation from the leaf classes is hard; compilers have to generate two copies of each constructor and destructor to handle those cases. – Davis Herring Apr 11 '20 at 02:24

0 Answers0