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