How do I call the parent movement mechanism in a diamond template?

Consider the following diamond-like multiple inheritance:

class base; class d1 : virtual public base; class d2 : virtual public base class d3 : public d1, public d2; 

base is a move-only class (having a large buffer just for moving). So d1 , d2 and d3 . Move constructor constructor d1 and d2 call << 21>.

Then what should the d3 move constructor do? Calling both the d1 and d2 moves fails (because the base move constructor is called twice.

Here I have a minimal compiled instance of the problem:

 #include <iostream> struct moveonly { moveonly(): data(nullptr) {} moveonly(const moveonly &) = delete; moveonly(moveonly &&other) { this->data = other.data; other.data = nullptr; } ~moveonly() { if(data) delete[] data; } char *data; }; class base { public: base() = default; base(const base &) = delete; base(base &&other) : d(std::move(other.d)) { } virtual ~base() = default; int a; int b; moveonly d; }; class d1 : virtual public base { public: d1() = default; d1(const base &) = delete; d1(d1 &&other) : base(std::move(other)) { } int x; int y; }; class d2 : virtual public base { public: d2() = default; d2(const base &) = delete; d2(d2 &&other) : base(std::move(other)) { } int r; int s; }; class d3 : public d1, public d2 { public: d3() = default; d3(const base &) = delete; // What should I do here? d3(d3 &&other) : d1(std::move(other)), d2(std::move(other)) { } int p; int q; }; int main() { d3 child; child.d.data = new char[1024]; for(size_t i = 0; i < 1024; ++i) child.d.data[i] = i * 2; d3 other_child = std::move(child); for(size_t i = 0; i < 1024; ++i) { std::cerr << other_child.d.data[i] << ' '; } std::cerr << std::endl; return 0; } 
+5
source share
2 answers

As in all virtual inheritances, virtual databases are initialized by the most derived object, therefore:

 d3(d3 &&other) : base(std::move(other)), // <== *you* initialize the base d1(std::move(other)), d2(std::move(other)) {} 
+7
source

What is wrong if you ask the compiler to provide an implementation?

d3 (d3 &) = default; // I think this is the best approach, as this is less error.

You can write this if you want:

d3 (d3 & other): base (std :: move (other)), d1 (std :: move (other)), d2 (std :: move (other)) {

}

-1
source

Source: https://habr.com/ru/post/1273128/


All Articles