One more time about this, but the related questions do not answer my question.
The standard is pretty clear:
12.8 Copying and moving class objects,
§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.
[ 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 ]
So, before noticing the "Note" at the end, I expected this piece of code to fail compilation (although I knew, that moving should fallback to copying):
#include <iostream>
using std::cout;
class c
{
public:
c() { cout << "c::c()\n"; }
c( std::initializer_list< int > ) { cout << "c::c( std::initializer_list )\n"; };
c( const c& ) { cout << "c::c( const c& )\n"; }
c& operator=( const c& ) { cout << "c& c::operator=( const c& )\n"; return *this; }
~c() { cout << "c::~c()\n"; }
void f() {}
};
void f( c&& cr ) { cout << "f()\n"; cr.f(); }
int main()
{
c x;
f( std::move( x ) );
return 0;
}
Then I saw the note at the end, but I was still surprised, that the code above outputs:
c::c()
f()
c::~c()
Note the "missing" c::c( const c& )
. Then I added
c( c&& ) = delete;
c& operator=( c&& ) = delete;
and the result is still the same.
What do I miss here?
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609
Compiler flags: -s -O0 -march=native -pthread -std=c++11 -Wall -Wextra -DNDEBUG
.