samedi 8 février 2020

Defaulted destructor in base class disable move constructor in child class if there is a member

Why does defaulted (user declared) destructor in Base1 prevent generation of move constructor/operator in Child1 class, but everything work fine when I move member data from Base (Base2) to Child (Child2) class?

struct Data {
    Data() {}
    Data(Data&&) noexcept { cout << "Move constructor" << endl; }
    Data& operator=(Data&&) noexcept {
        cout << "Move assign" << endl;
        return *this;
    }
    vector<int> vec;
};

struct Base1 {
    virtual void fun() { cout << "Base1::fun" << endl; }
    virtual ~Base1() = default;
    Data data;
};

struct Child1 : public Base1 {
    void fun() override { cout << "Child1::fun" << endl; }
};

struct Base2 {
    virtual void fun() { cout << "Base2::fun" << endl; }
    virtual ~Base2() = default;
};

struct Child2 : public Base2 {
    void fun() override { cout << "Child2::fun" << endl; }
    Data data;
};

int main() {
    Child1 c1;
    auto obj1 = std::move(c1);  // error

    Child2 c2;
    auto obj2 = std::move(c2);
}

My current understanding is that when I declare destructor as “default” in Base (BaseDel), then move constructor should be “deleted” in Base (BaseDel) and in Child (ChildDel) class. Is this correct? Member location shouldn’t matter, I think. If I do that explicit, I get expected error:

struct BaseDel {
    BaseDel() {}
    virtual void fun() { cout << "BaseDel::fun" << endl; }
    BaseDel(BaseDel&& st) = delete;
    virtual ~BaseDel() = default;
};

struct ChildDel : public BaseDel {
    ChildDel() {}
    void fun() override { cout << "ChildDel::fun" << endl; }
    Data data;
};

int main() {
    ChildDel cd;
    auto objd = std::move(cd);  // OK, expected error
}

Aucun commentaire:

Enregistrer un commentaire