You're right that it could work in this particular case and on most common platforms. However, it would be a terrible can of worms to allow this generally.

Consider that the standard doesn't guarantee all data pointers to be of the same size (for example, there are platforms where char* is larger than int*, because they don't have individually addressible bytes). The fact that you can convert a pointer-to-derived into a pointer-to-base does not mean that this conversion is trivial and does not affect the representation in memory. After all, as soon as multiple inheritance enters the picture, even this conversion start to involve changing the value of the pointer.

At the same time, templates are quite opaque in general. We know that a sane implementation of std::vector<T*> will use the same layout for its data for all Ts, as long as T* are the same size. But in general, a template can do anything based on its template arguments, with totally incompatible data layout.

Not to mention specialisation - if the template was specialised for <ChildOne*>, it could be totally incompatible.

Yes, there are cases where a const reference to a particular implementation of a template instantiated with Parent* could be aliased to the same template instantiated with ChildOne*. But these are extremely fragile, and in the general case such substitutability would allow innumerable bugs.

If you know that on your platform with your implementation of the standard library and with your types it's safe, you can create a casting function for it: