Reputation: 217235
I already heard that std::vector<T>::iterator
can simply be T*
instead of an iterator class.
But is it really legal?
Pointer arithmetic only applies to array and std::vector
doesn't create array object (T[]
) but contiguous objects (via placement new).
Moreover I think that std::launder
would even be required (C++17) to access individual element (as we can read in comment of static_vector
example of std::aligned_storage
).
I think it is roughly equivalent to following that I think is undefined behavior.
template <typename T, std::size_t N, typename F>
void test_array(F func)
typename std::aligned_storage<sizeof (T) * N, alignof (T)>::type data;
char* buffer = &data;
for (std::size_t i = 0; i != N; ++i) {
new (buffer + i * sizeof(T)) T;
}
T* array = reinterpret_cast<T*>(buffer);
for (std::size_t i = 0; i != N; ++i) {
func(array[i]); // UB for (0 < i) ?
}
for (std::size_t i = 0; i != N; ++i) {
array[i].~T();
}
}
Upvotes: 6
Views: 191
Reputation: 179799
std::vector::iterator
is part of the Standard Library, and therefore part of the implementation. That means it may depend on implementation-specific details. In particular, the implementation may use pointer arithmetic in a non-portable way. If the implementation knows a T[]
is indistinguishable from contiguously allocated T's
, then it can do pointer arithmetic on them.
Upvotes: 6