sap
sap

Reputation: 1228

moving class (with no default constructor) inside the move constructor of another class

so i have a class with deleted copy ctor/assignment, no default ctor, and has move ctor/assignment:

class A {
  int data_ = 0;

public:
    A(const A& other) = delete;
    A& operator=(const A& other) = delete;

    A(int data) : data_(data) {}
    ~A() {}

    A(A&& other) { *this = std::move(other); }
    A& operator=(A&& other) {
        if (this != &other) {
            data_ = other.data_;
            other.data_ = 0;
        }
        return *this;
    }
};

and i have a class B (also no default ctor) that contains A:

class B {
    A a;

public:
    B(const B& other) = delete;
    B& operator=(const B& other) = delete;

    B(int data) : a(data) {}
    ~B() {}

    B(B&& other) { *this = std::move(other); }
    B& operator=(B&& other) {
        if (this != &other) {
            a = std::move(other.a);
        }
        return *this;
    }
};

now the problem is the B move ctor wont compile, because he says theres no default constructor for A, and this is really annoying, i dont want him to create a new A instance when i call the move ctor on B, i want it to move it!

so theres 2 things i could do:

B(B&& other) : a(std::move(other.a)) { *this = std::move(other); }

this wont work, because in the move assignment he will try to move A again.. also if "this == &other == true" he will have moved A from himself making A garbage now..

another way:

make a default private A ctor. make B friend of A. but that sounds so hacky and ugly.. what is the best way to deal with this situation? i really want to avoid having to make a default constructor for A.

thanks in advance.

Upvotes: 1

Views: 370

Answers (2)

Mr.WorshipMe
Mr.WorshipMe

Reputation: 763

The solution would be to do this:

class A {
  int data_ = 0;

public:
    A(const A& other) = delete;
    A& operator=(const A& other) = delete;

    A(int data) : data_(data) {}
    ~A() {}

    A(A&& other) : data_(other.data_) { other.data_ = 0; }
    A& operator=(A&& other) {
        if (this != &other) {
            data_ = other.data_;
            other.data_ = 0;
        }
        return *this;
    }
};

class B {
    A a;

public:
    B(const B& other) = delete;
    B& operator=(const B& other) = delete;

    B(int data) : a(data) {}
    ~B() {}

    B(B&& other) : a(std::move(a)) {  }
    B& operator=(B&& other) {
        if (this != &other) {
            a = std::move(other.a);
        }
        return *this;
    }
};

Although, since A only contains an int in it, it would not result in better performance than a copy...

Upvotes: 1

msrd0
msrd0

Reputation: 8400

Since you have an Object of A declared in your class B, you need to create it when you construct B. A normal Object in C++ can't have no value and it could not be created (cause there is no default constructor).

To fix your problem, make a pointer to a that can have the value 0, so it needn't to be created in your constructor. Change this line:

A a;

into this:

private:
    A *a = 0;

Upvotes: 0

Related Questions