*ap
is an lvalue (§ 5.3.1.1, n3290) which is in general not safe for the move to happen automatically. The local variable return a;
is a different case. There's no requirement for the compiler to prove that in this specific instance it would be safe. This is another good reason for not using pointers in cases where you don't really want pointer semantics.
Changing it to:
return std::move(*ap);
will cause it to be explicitly moved however.