Summary
Don't delete the move members.
Assuming your compiler is completely C++11 conforming, then explicitly deleting the move constructor will also implicitly declare the following:
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
That is if you declare a move constructor (or move assignment operator), and do not declare copy members, they are implicitly declared as deleted. So your complete class Foo is as if:
class Foo
{
public:
Foo(int i) : i_(i) {}
Foo(Foo&&) = delete;
Foo(const Foo&) = delete; // implicitly declared
Foo& operator=(const Foo&) = delete; // implicitly declared
int i_;
};
Now vector<Foo>::push_back(Foo(1))
requires that Foo
be MoveConstructible
. MoveConstructible
could be satisfied by an accessible move constructor, or even by an accessible copy constructor. But Foo
has neither. To fix you could:
class Foo
{
public:
Foo(int i) : i_(i) {}
Foo(const Foo&) = default;
Foo& operator=(const Foo&) = default;
int i_;
};
I.e. default the copy members and remove the deleted move member.
In general it is not a good idea to explicitly delete the move members. If you want a class to be copyable but not "movable", just declare exactly as you would in C++03: declare/define your copy members. You can let the copy members be compiler-generated with = default
, and that still counts as a user-declaration. And don't declare move members. Move members that don't exist are not the same as deleted move members.
Deleted move members mean you can not construct a copy of Foo
from an rvalue, even if the copy constructor would have worked fine to do so. This is rarely the desired intent.
Even if you want your class to not be copyable nor movable, it is better to just delete the copy members and leave the move members undeclared (meaning they won't exist). If you're ever reviewing code (including your own), and see deleted move members, they are almost certainly incorrect, or at the very best superfluous and confusing.
Some day someone will come up with a good use case for deleted move members. But it will be a rare use case. If you see such a pattern in code, you should expect the code author to have a very good explanation. Otherwise, deleted move members are likely to just be incorrect (at best superfluous). But on the bright side this error will show itself at compile time, instead of at run time (as in your example).
Here is a summary chart of what the compiler will implicitly do when you explicitly declare any of the special members. Those squares colored red represent deprecated behavior.
= default
and = delete
count as user-declared.
Click here if you would like to view the full slide deck.