In this post https://mcmap.net/q/356669/-checking-the-object-type-in-c-11, I have the comment:
In C++11 you'll actually want to do virtual ~A() = default;
Otherwise, you'll lose the implict move constructors.
The comment is incorrect.
Even default
ed, that destructor is "user-declared" (though note that it is not also "user-provided").
#include <iostream>
struct Helper
{
Helper() {}
Helper(const Helper& src) { std::cout << "copy\n"; }
Helper(Helper&& src) { std::cout << "move\n"; }
};
struct A
{
virtual ~A() {}
Helper h;
};
struct B
{
virtual ~B() = default;
Helper h;
};
struct C
{
Helper h;
};
int main()
{
{
A x;
A y(std::move(x)); // outputs "copy", because no move possible
}
{
B x;
B y(std::move(x)); // outputs "copy", because still no move possible
}
{
C x;
C y(std::move(x)); // outputs "move", because no user-declared dtor
}
}
+ g++-4.8 -std=c++11 -O2 -Wall -pthread main.cpp
+ ./a.out
copy
copy
move
So you haven't "lost" anything — there was no move functionality there to begin with!
Here is the standard passage that prohibits an implicit move constructor in both cases:
[C++11: 12.8/9]:
If the definition of a class X
does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
X
does not have a user-declared copy constructor,
X
does not have a user-declared copy assignment operator,
X
does not have a user-declared move assignment operator,
X
does not have a user-declared destructor, and
- the move constructor would not be implicitly defined as deleted.
Bootnote
It wouldn't hurt if a future version of the standard actually listed the precise meanings of terms such as "user-declared". There is, at least, this:
[C++11: 8.4.2/4]:
[..] A special member function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. [..]
One may assume the distinction here by implication.
A(A&&) = default;
– Boliviano