According to the standard,
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if
The behavior can essentially be illustrated with:
void foo(const int& i)
{
std::cout << "copy";
}
void foo(int&& i)
{
std::cout << "move";
}
When both overloads are present, the int&&
overload is selected for rvalues while the const int&
overload is selected for lvalues. If you remove the int&&
overload, const int&
is called (ergo, not an error) even for rvalues. This is essentially what's happening in this case:
class Foo
{
public:
Foo() = default;
Foo(Foo const &) = delete;
};
Overload resolution only sees one candidate but since it is explicitly deleted, the program is ill-formed.
The non-normative note below the section you quoted clarifies this is what's happening:
[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. — end note ]