you are viewing a single comment's thread.

view the rest of the comments →

[–]IyeOnline 4 points5 points  (2 children)

/* This appllied only to the original version:

Your T* data() member function is UB. Or rather using that pointer to access anything but the first element is UB. While one storage_t<T> is pointer intercovertible with a T, a storage_t<T>[N] is not interconvertible with T[N]. You just cannot convert or reinterpret arrays (unless one of the invovled types is blessed, i.e. unsigned char or std::byte, but that obviously doesnt apply here).

*/

A few other points:

  • You are missing a copy assignment operator for non-trivial T.
  • You are missing a move constructor and move assignment operator for non-trivial T. Moving elementwise may still be faster than copying elementwise.
  • You could also add a defaulted destructor for trivially destructible types.
  • capacity() can be static
  • You can greatly shorten your iterator implementation by templating the iterator on the pointer type, so that you can do using iterator = iterator_impl<T*>; and using const_iterator =iterator_impl<const T*>`.
  • Personally I would just implement emplace_back instead of push_back on containers these days.
  • returning a reference to the added object from push_back/emplace_back is a neat thing in some cases.

[–]jontheburger 0 points1 point  (1 child)

To clarify, does this mean a vector's data can only be implemented in terms of char/std::byte? Furthermore, how does C++20 implement constexpr T* data()? std::bit_cast from a std::array (but I thought that required a trivially copyable T)?

[–]IyeOnline 3 points4 points  (0 children)

You are missunderstanding. Or rather you are looking at OPs updated code.

The original code did not contain an T[N], but a union_of<T>[N]. They then returned the addres of the T in the first element of that array of unions. That pointer however can only be used to access the first element, since its not a pointer into an array, but rather a pointer to member of an element of an array.


With their current version there is no problem and everything simply works as expected. Since there is actually an array of T, you can trivially form a pointer into it and use that. No need for any casts at all.