Using copy ctor instead of moving ctor when the derivative has a destructor defined

When I add a destructor to my derived class, I get compiler errors (using gcc 4.7) when it tries to use a copy of ctor instead of a specific ctor move:

#include <utility> #include <iostream> template <typename T> struct Base { T value; Base(T&& value) : value(value) { std::cout << "base ctor" << std::endl; } Base& operator=(const Base&) = delete; Base(const Base&) = delete; Base& operator=(Base&& rhs) { value = rhs.value; std::cout << "move assignment" << std::endl; } Base(Base&& other) : value(other.value) { std::cout << "move ctor" << std::endl; } virtual ~Base() { std::cout << "base dtor" << std::endl; } }; template <typename T> struct Derived : public Base<T> { Derived(T&& value) : Base<T>(std::forward<T>(value)) { std::cout << "derived ctor" << std::endl; } ~Derived() { std::cout << "derived dtor" << std::endl; } }; template <typename T> Derived<T> MakeDerived(T&& value) { return Derived<T>(std::forward<T>(value)); } struct Dummy {}; int main() { auto test = MakeDerived(Dummy()); } 

This code compiles in gcc-4.5 and gcc-4.6. The errors from gcc-4.7 are as follows:

 test.cpp: In function 'int main()': test.cpp:61:34: error: use of deleted function 'Derived<Dummy>::Derived(const Derived<Dummy>&)' test.cpp:37:8: note: 'Derived<Dummy>::Derived(const Derived<Dummy>&)' is implicitly deleted because the default definition would be ill-formed: test.cpp:37:8: error: use of deleted function 'Base<T>::Base(const Base<T>&) [with T = Dummy; Base<T> = Base<Dummy>]' test.cpp:16:3: error: declared here test.cpp: In instantiation of 'Derived<T> MakeDerived(T&&) [with T = Dummy]': test.cpp:61:34: required from here test.cpp:54:43: error: use of deleted function 'Derived<Dummy>::Derived(const Derived<Dummy>&)' 

Am I missing something here or should it also compile gcc 4.7? When I comment on the Derived class destructor, everything is fine.

 gcc version 4.5.3 (Ubuntu/Linaro 4.5.3-12ubuntu2) gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-11precise2) 
+4
source share
1 answer

The error is correct; move constructors are only generated implicitly when the class does not have a user-defined destructor. If you add a destructor, then you suppress the default move-construct constructor, and a copy constructor is created. By default, instance constructor generation is suppressed when the class has an unpublished base class, as yours, so Derived is neither copyable nor movable.

The solution is to add the move constructor to Derived .

+1
source

All Articles