Puzzling default move constructor

I am running gcc 4.7 on fedora 17 on 32-bit x86.

Below, is source code that illustrates the puzzler: The compiler complains about a missing move constructor. When I supply the move constructor, the program compiles, links and runs successfully, but the move constructor is not executed (the print statement in the constructor is not invoked).

Here is the source code that produces the compile-time error:
tmove.cpp:28:13: error: use of deleted function ‘X::X(X&&)’
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
using namespace std;

class X
{
public:
  ~X() = default;
  X( void ) = default;
  X( const X& ) = default;
  X& operator=( const X& ) = default;

#if 1
  X( X&& ) = delete;
#else
  X( X&& )
  {
    cout << "In X( X&& )" << endl;
  }
#endif

  X& operator=( X&& ) = delete;
};

static X f( X& v )
{
  cout << "f" << sizeof( v ) << endl;

  return X(v);      //<<<----------- Line 28
}// f

int main( int argc, char* argv[] )
{
  X x;

  f(x);

  return 0;
}// main 

Changing "#if 1" to "#if 0", fixes error, with the program output:
f1

i.e. it appears the X move constructor was not invoked.
So, why is the compiler complaining that it needs this move constructor?
Since your function returns a temporary object by value, the compiler optimizes the move per the usual copy elision rules ((U)RVO, specifically):

http://en.cppreference.com/w/cpp/language/copy_elision

one of the requirements for copy elision is that the appropriate copy or move constructor is accessible, even though it is never called.
Thanks. I'd heard about this, but have never been bit before, so I did not clue in.
I want to know where this is happening, in case I have coded something not as I would wish,
so the -fno-elide-constructors flag is useful during development, to be able to step into the code where the elision would be happening.
Topic archived. No new replies allowed.