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

--- Comment #17 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to user202729 from comment #16)
> That sound like a good idea, thanks. I thought about this some time earlier
> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115413#c3) but I did not know
> how to check the implementation of `destroy()`.

You only need to know if Alloc::destroy exists or not.

> Nevertheless, this does not handle the case of devirtualization in vector
> access (e.g. `v[0].f()` where v is a vector and method f is virtual). What
> do you think?

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();

I'm not even 100% convinced that the destructor optimization is valid, but I
think any time there is pointer arithmetic on the vector's storage, the dynamic
types of objects in the array must match the static types. Arguably the v[0]
access above already requires that, so maybe the code above isn't valid, but I
don't think it's entirely clear from the standard.

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();

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.

> Apart from that, being do you think it is common for the user to override
> `destroy()` (in a template specialization) but still call the destructor
> inside it? In that case the proposal would not optimize that case.

I don't really care about that, we can't handle every case.

Reply via email to