Given that std::copy
(for Trivial Types obviously) can only be implemented as a wrapper around memmove(*), I'm wondering:
memcpy
? (I can't count the number of times I forgot to multiply by sizeof
.)memcpy
wrapper that does the sizeof
multiplication automatically?(*): C++ Standard Library implementations (from back MSVC 2005(!) up to modern MSVC2015, libc++ etc.) decay std::copy
TriviallyCopyable types to memmove
. Bot not to memcpy
. Because:
std::copy(src_first, src_last, destination_first)
defines that:
The behavior is undefined if
d_first
is within the range[first, last)
.
d_first
can be "to the left" of the source range, and the destination range can extend into the source range.For std::memcpy
the definition is that
If the objects overlap, the behavior is undefined.
For std::memmove
, the definition is:
The objects may overlap: copying takes place as if the characters were copied to a temporary character array and then the characters were copied from the array to dest.
Given this, it is clear that you can use std::memove
to implement std::copy
for TrivialllyCopyable types, because memmove doesn't impose any restrictions and the dispatch to the correct implementation can be done at compile time via type traits --
but it's hard to implement std::copy
in terms of memcpy
because (a) the check whether the pointer ranges overlap would have to be done at run time, and (b) even implementing the runtime check for unrelated memory ranges could be quite a mess.
So, this leaves us with
void* memcpy( void* dest, const void* src, std::size_t count );
a function with a less than stellar interface, where you constantly need to multiply the input count of non-char objects with their sizeof
and that is totally untyped.
But memcpy is fastest (and by quite a margin, measure it yourself), and when you need fast copies of TriviallyCopyable types, you reach for memcpy. Which superficially should be easy to wrap in a type safe wrapper like:
template<typename T>
T* trivial_copy(T* dest, T* src, std::size_t n) {
return static_cast<T*>(std::memcpy(dest, src, sizeof(T) * n));
}
but then, it's unclear wether you should do compile time checks via std::is_trival
or somesuch and of course there may be some discussion whether to go with the exact memcpy
signature order, yadda yadda.
So do I really have to reinvent this wheel myself? Was it discussed for the standard? Etc.
To clarify the difference between mencpy and memove, according to the docs memmove can copy memory to a location that overlaps the source memory, for memcpy this is undefined behavior.
"The objects may overlap: copying takes place as if the characters were copied to a temporary character array and then the characters were copied from the array to dest."
Is there a Standard C++ type-safe wrapper for the times you need memcpy? (I can't count the number of times I forgot to multiply by sizeof.)
Yes, std::copy (maybe, explained below)
If there's nothing in the standard, have there been any proposals for this? If not, why not?
As far as i know the standard does not enforce the usage of memmove/memcpy for std::copy for trivial types. So it's up the implementation. For example in visual studio update 2015 update 2 they did use memmove to speed things up:
"Increased the speed of std::vector reallocation and std::copy(); they are up to 9x faster as they call memmove() for trivially copyable types (including user-defined types)."
Are there any specific obstacles in providing a memcpy wrapper that does the sizeof multiplication automatically?
No, in fact you can implement this yourself by using std::is_trivial
Edit:
According to this document section 25.3.1 there are no restrictions to std::copy implementation only complexity:
Complexity: Exactly last - first assignments.
And this makes perfect sense when you consider that memcpy uses cpu speciffic instruction (that are not available on all cpus) to speed up memory copy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With