Given that std::copy
(for Trivial Types obviously) can only be implemented as a wrapper around memmove(*), I'm wondering:
- 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 bysizeof
.) - If there's nothing in the standard, have there been any proposals for this? If not, why not?
- Are there any specific obstacles in providing a
memcpy
wrapper that does thesizeof
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)
.- Only the beginning of the destination range MUST NOT be within the source range. The destination range is allowed to extend into the source range. That is,
d_first
can be "to the left" of the source range, and the destination range can extend into the source range.
- Only the beginning of the destination range MUST NOT be within the source range. The destination range is allowed to extend into the source range. That is,
For
std::memcpy
the definition is thatIf the objects overlap, the behavior is undefined.
- That is, the full ranges must not overlap: This is what allows memcpy to be the fastest variant, because it can just assume that the memory of source and destination is completely disjoint.
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.
- That is, the source and destination range may arbitrarily overlap, there is no restriction.
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.