https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110057

--- Comment #18 from user202729 <user202729 at protonmail dot com> ---
(In reply to Jonathan Wakely from comment #17)
> I don't think that optimization would be valid. Users could do disgusting
> things like this (as long as sizeof(Base) == sizeof(Derived)):
> 
> std::vector<Base> v(1);
> v[0].~Base();
> ::new((void*)v.data()) Derived();
> v[0].f();
> v[0].~Derived();
> ::new((void*)v.data()) Base();

According to "n.m." on StackOverflow, that code is illegal
https://stackoverflow.com/questions/76380436/is-placement-new-of-derived-type-within-a-vector-array-of-base-type-legal#comment134688951_76380436

So I guess we're safe if the comment is correct. (Same for the vector
destructor case)

> This certainly seems to be allowed:
> 
> std::vector<Base> v(1);
> Base* p = v.data();
> p->~Base();
> ::new((void*)p) Derived();
> p->f();
> p->~Derived();
> ::new((void*)p->) Base();

The clause seems to apply just as well, you cannot access the newly constructed
`Derived` object through `p`.

Further reading:
https://stackoverflow.com/questions/62642542/were-all-implementations-of-stdvector-non-portable-before-stdlaunder

> If we can be sure that v[0] requires the static and dynamic types to match,
> then we could do something like:
> 
>       reference
>       operator[](size_type __n) _GLIBCXX_NOEXCEPT
>       {
>       __glibcxx_requires_subscript(__n);
> #ifdef __cpp_rtti
>         if (typeid(this->_M_impl._M_start[__n]) != typeid(value_type))
>           __builtin_unreachable();
> #endif
>       return *(this->_M_impl._M_start + __n);
>       }
> 
> I have no idea whether that would help anything, or if the use of typeid
> would actually pessimize things.

It turns out that the compiler can currently prove (with optimization enabled)
that `typeid::operator==` is pure, so it wouldn't pessimize things. If you want
to be extra careful I suppose `#if __OPTIMIZE__` is an option.

Reply via email to