These are fair points and issues like these are why many larger projects have their own custom vector-like classes. One thing I did want to call attention to is your point that C++ best practices require that objects be in well-defined states except inside methods. That's true, although it's not a language requirement, but in many cases you can get the best of both worlds through the use of lambdas. A simple example to give the flavor:
template <typename Function>
void my_vector::munge(Function initialize_gap) {
create_uninitialized_gap();
// Some of our elements now contain uninitialized memory.
// We don't want to expose this to arbitrary code, but
// it's OK to expose this to the function the user
// provided specifically to handle this.
initialize_gap(gap_begin(), gap_end());
// The gap is now initialized, so when we return from
// this method, we'll be in a well-defined state.
}
This is the standard pattern you use for such things in functional languages, and it works very well. The idea is to ensure that intermediate states are only seen by code that explicitly expects to handle them.