Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 707
Dmitry Avatar asked Aug 25 '16 07:08

Dmitry


People also ask

How is a derived class different from its base class?

A base class is an existing class from which the other classes are derived and inherit the methods and properties. A derived class is a class that is constructed from a base class or an existing class.

What does derived class does not Inhent from the base class?

Following are the properties which a derived class doesn't inherit from its parent class : 1) The base class's constructors and destructor. 2) The base class's friend functions. 3) Overloaded operators of the base class.

Does a derived class inherits a base class constructor by default?

In inheritance, the derived class inherits all the members(fields, methods) of the base class, but derived class cannot inherit the constructor of the base class because constructors are not the members of the class.

What happens when a derived class object is created?

When a derived class object is created using constructors, it is created in the following order: Virtual base classes are initialized, in the order they appear in the base list. Nonvirtual base classes are initialized, in declaration order.


1 Answers

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.

like image 97
Brian Bi Avatar answered Sep 24 '22 22:09

Brian Bi