To copy from a C++20 std::span into an std::vector I can simply do the following:
void WriteBuffer(std::vector<std::byte>& destData, const std::span<const std::byte>& srcData)
{
std::copy(srcData.begin(), srcData.end(), destData.end());
}
..which will be optimised to a single memmove. See example: https://godbolt.org/z/8nPjzj3c6
However, if I replace std::span with gsl::span we don't get this optimisation anymore: https://godbolt.org/z/MWfPKW8eq
Is it best to instead resize the vector and use std::memcpy to copy over the data, or are there better alternatives?
My understanding is that gsl::span does not get optimised, because it's using a custom iterator that the implementation of std::copy is not aware of - so it cannot make assumptions about the linearity of the data - is that right? If so, I suppose all STL containers and algorithms will have the same issue with gsl::span and any other data structures that use custom iterators. But please let me know if I've misunderstood something.
Update: Sorry, there was a mistake here. As @Caleth kindly pointed out, I'm writing out of bounds. However, resizing first and then using copying to destData.begin() (yes overwriting, just for simplicity..) doesn't really change it - it still copies byte-by-byte.
Not really. The standard library would see this member and have the same knowledge about the data layout.
The more likely reason is that the iterator operations are checked at runtime, rather than the "undefined behaviour when misused" of
std::span.If you were to read out of range of
srcData, usingstd::spanthe behaviour is undefined. Usinggsl::span, the behaviour is defined,std::terminateis called. The "missing optimisations" are probably becausememcpying out of range data is not the same as callingstd::terminateYour example code exhibits undefined behaviour when
srcDatahas any elements, because you can't write past the end of a vector.