Why g++ didn't choose move constructor

For this program source code:

#include <cstdio>
#include <utility>
namespace {
int ID;
struct T {
T(): id(++ID) {
printf("construct %d\n", id);
}
T(const T &two): id(++ID) {
printf("copy construct %d from %d\n", id, two.id);
}
T(T &&two): id(++ID) {
printf("move construct %d from %d\n", id, two.id);
}
T &combine(const T &two) {
printf("combine %d with %d\n", id, two.id);
return *this;
}
T foo(const T &two) const {
return T(*this).combine(two);
}
T bar(const T &two) const {
return std::move(T(*this).combine(two));
}
~T() {
printf("destroy %d\n", id);
}
int id;
};
}
int main() {
T a, b;
T c(a.foo(b));
T d(a.bar(b));
}

For class T, both copy and move constructors are defined. The combine function combines two object of T, calling object is altered with the result. Function foo and bar try to get the combine result without alter either object. This is done by copy the calling object, combine with the other and return the result. Since the return result will be destroyed right after return, the compiler should choose the more efficient move constructor when both copy and move are defined. But when I call foo as in object c in main, copy constructor are used. Bar is identical to foo, except it add std::move around the return result, resulting move constructor to be used. Why for function foo, the compiler didn't choose move constructor?

Here is the output of the program:

construct 1
construct 2
copy construct 3 from 1
combine 3 with 2
copy construct 4 from 3
destroy 3
copy construct 5 from 1
combine 5 with 2
move construct 6 from 5
destroy 5
destroy 6
destroy 4
destroy 2
destroy 1
Hey, OP, can I interest you in some formatting?
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
39
40
#include <cstdio>
#include <utility>

namespace {

int ID;

struct T {
    T(): id(++ID) {
        printf("construct %d\n", id);
    }
    T(const T &two): id(++ID) {
        printf("copy construct %d from %d\n", id, two.id);
    }
    T(T &&two): id(++ID) {
        printf("move construct %d from %d\n", id, two.id);
    }
    T &combine(const T &two) {
        printf("combine %d with %d\n", id, two.id);
        return *this;
    }
    T foo(const T &two) const {
        return T(*this).combine(two);
    }
    T bar(const T &two) const {
        return std::move(T(*this).combine(two));
    }
    ~T() {
        printf("destroy %d\n", id);
    }
    int id;
};

}

int main() {
    T a, b;
    T c(a.foo(b));
    T d(a.bar(b));
}

But when I call foo as in object c in main, copy constructor are used. Bar is identical to foo, except it add std::move around the return result, resulting move constructor to be used. Why for function foo, the compiler didn't choose move constructor?
The compiler can rewrite that invocation to directly construct c in-place inside T::foo(). Notice that there was no additional copy-construction or move-construction for c. If you were to print c.id it would display 4 (actually it would be undefined, since you never initialized ID, but that's neither here nor there).
Thanks hellos for formatting the source code. For the line 38 call, there are two copy constructor calls, copy constructor 3 from 1, caused by T(*this) inside foo function; another copy constructor 4 from 3, caused by copying return value of foo to variable c in main. My question was the second copy constructor 4 from 3, why it didn't use move constructor. (By the way, ID is static, and so is defined to have 0 value at the beginning.)
In the future when posting code a couple of points to read about:

PLEASE learn to use code tags, they make reading and commenting on source code MUCH easier.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

HINT: you can edit your post and add code tags.

Some formatting & indentation would not hurt either
Topic archived. No new replies allowed.