Why does an explicitly defaulted destructor disable default move constructor in the class? I know that it does, as explained in several existing answers. (e.g. Explicitly defaulted destructor disables default move constructor in a class )
I want to know why: what is the rationale for this, when it doesn't actually do anything that implies that the move constructor might need to have custom code? In fact, we recommend that people use =default
rather than an empty body because that way the compiler knows it doesn't do anything beyond the automatic actions, exactly as if it had been automatically generated without any declaration.
To be really really clear, I know why defining a destructor with your own logic in it should suppress autogeneration. I'm pointing out that =default
doesn't change anything as compared with letting the compiler implicitly generated it, so that reason does not apply here.
I recall >10 years ago there was a lot of discussion on what is the right way to specify it. I don't remember, if I ever learned, why it went the way it did in the end. Does anyone know of a compelling reason why this is a specific desirable feature in itself, or some technical reason why it ought to be this way?
demonstration: https://gcc.godbolt.org/z/86WGMs7bq
#include <type_traits>
#include <utility>
#include <string>
#include <iostream>
struct C
{
std::string s;
C () : s{"default ctor"} {}
// ~C() = default; // <<< comment this line out, and we see that original.s has its contents "stolen"
// <<< with this dtor declared, the original string is copied.
};
int main()
{
C original;
original.s = "value changed";
C other { std::move(original) };
using std::cout;
cout << "original now: " << original.s << '\n';
cout << "other is: " << other.s << '\n';
}
This rule is stated in cppreference and was mentioned the other day in a C++ conference video that was just posted, which reminded me of it.
std::is_move_constructible
isn't the right way to check this. From cppreference: "Types without a move constructor, but with a copy constructor that accepts const T& arguments, satisfy std::is_move_constructible." – JedediahCanMove::CanMove(CanMove&&)
andCannotMove::CannotMove(CannotMove const&)
– JedediahThe special copy member functions and the destructor disable move support. The automatic generation of special move member functions is disabled (unless the moving operations are also declared). However, still a request to move an object usually works because the copy member functions are used as a fallback (unless the special move member functions are explicitly deleted).
– Sarre=default
, so that does not apply. Is my question (e.g. 2nd paragraph) not clear? This A does not address this at all, and in fact begs this question as a corollary. – Flowers=default
doesn't change anything", but it does change something: you wrote it. If you wrote it, then you wrote it for a reason. You're saying something about the type. – Archipenko