In theory erase could return a move iterator, meaning that you could omit the call to std::move. This wouldn't be backwards compatible though so not going to happen.
There is no erase that takes an index, so I assume that n = a.end(). Also it is missing a dereference:
a[i] = std::move(*a.erase(a.end()-1));
but erasing the one-before-the-end returns the (new) end iterator, which obviously is not referenceable. In general, after calling erase, it is too late to access the erased element.
You want something like:
template<class Container, class Iter>
auto erase_and_return(Container&& c, Iter pos)
{
auto x = std::move(*pos);
c.erase(pos);
return x;
}
Also in the general case it doesn't make sense for erase to return a move iterator.