You are not using the move constructor. I think swap is implemented something like this
Event a;
Event b;
Event temp(move(a)); // this one wants to use a move constructor
a = move(b);
b = move(temp);
You want to use the move assignment operator, which doesn't exist in your code, so it falls back to the copy assignment operator.
This is your problem:
return i ? tmp1 : tmp2;
A local variable in a function will only be moved from in the return statement if the return statement is just return var;
. If you want to do that test you will need to use an if:
if (i) {
return tmp1;
} else {
return tmp2;
}
The citation is a bit convoluted, but it is in 12.8/31 and 12.8/32
12.8/32 When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue [...]
That is even if the expression is an lvalue, it will be considered to be an rvalue when the criteria in 12.8/31 is met, the second option in that block is:
12.8/31 in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value.
Which determines that return tmp;
allows for copy elision, but return (cond?tmp:tmp);
doesn't.
Note that for the compiler to generate an implicit std::move
in the return statement, the returned object must be a candidate for elision unless the it is also an argument to the function. Using the conditional operation inhibits copy elision, and at the same time inhibits the compiler from doing moving out of your objects. That second case might be simpler to code:
Foo make_foo(Foo src) {
return src; // Copy cannot be elided as 'src' is an argument
}
Best Answer
The compiler is performing copy elision, which is allowed per paragraph 12.8/31 of the C++11 Standard even if your move constructor, copy constructor, or destructor have side effects:
The term copy elision is used even when a move is being elided:
With GCC, you can use the
-fno-elide-constructors
to inhibit copy elision. In this case, you would see that the move constructor gets invoked, as in this live example.