Dmitry Dmitry - 3 months ago 31
C++ Question

Why is derived class move constructible when base class isn't?

Consider the following example:

#include <iostream>
#include <string>
#include <utility>

template <typename Base> struct Foo : public Base {
using Base::Base;
};

struct Bar {
Bar(const Bar&) { }
Bar(Bar&&) = delete;
};

int main() {
std::cout << std::is_move_constructible<Bar>::value << std::endl; // NO
std::cout << std::is_move_constructible<Foo<Bar>>::value << std::endl; // YES. Why?!
}


Why does the compiler generate a move constructor despite the base class being non-move-constructible?

Is that in the standard or is it a compiler bug? Is it possible to "perfectly propagate" move construction from base to derived class?

Answer

Because:

A defaulted move constructor that is defined as deleted is ignored by overload resolution.

([class.copy]/11)

Bar's move constructor is explicitly deleted, so Bar cannot be moved. But Foo<Bar>'s move constructor is implicitly deleted after being implicitly declared as defaulted, due to the fact that the Bar member cannot be moved. Therefore Foo<Bar> can be moved using its copy constructor.

Edit: I also forgot to mention the important fact that an inheriting constructor declaration such as using Base::Base does not inherit default, copy, or move constructors, so that's why Foo<Bar> doesn't have an explicitly deleted move constructor inherited from Bar.