On Fri, Feb 24, 2023 at 09:55:13AM +0000, Jonathan Wakely wrote:
> > You would still be accessing past the end of the
> > vec<vl_embed>::m_vecdata array which is UB.
>
> My thinking is something like:
>
> // New tag type
> struct vl_relative { };
>
> // This must only be used as a member subobject of another type
> // which provides the trailing storage.
> template<typename T>
> struct vec<T, va_heap, vl_relative>
> {
> T *address (void) { return (T*)(m_vecpfx+1); }
> const T *address (void) const { return (T*)(m_vecpfx+1); }
>
> alignas(T) alignas(vec_prefix) vec_prefix m_vecpfx;
> };
>
> template<typename T, size_t N /* = 0 */>
> class auto_vec : public vec<T, va_heap>
> {
> // ...
> private:
> vec<T, va_heap, vl_relative> m_head;
> T m_data[N];
>
> static_assert(...);
> };
Maybe this would work, vl_relative even could be vl_embed.
Because vl_embed I believe is used in two spots, part of
auto_vec where it is followed by m_data and on heap or GGC
allocated memory where vec<..., vl_embed> is followed by
further storage for the vector.
Jakub