Somehow, the native stl::copy()
algorithm on VC++ (Dinkumware) figures out that it can use memcpy()
on data that is trivially copy-able. Is it possible for a mere mortal to do that? - assuming each element is_trivially_copyable.
Does random_access_iterator imply contiguous memory? The standard is not clear to me.
So, if all you have in a template is an iterator or two, is it possible to deduce at compile-time that the underlying array can be copied with memcpy()
, and if so how?
EDIT - Here's my motivation. I have a routine that moves a block of data rather than copying it. To get speed when the data are memmove-able, I've made it call stl::copy sometimes. I was wondering if that is the only way. (As a kid, I would always try this at home.)
// Move a range of values
template<class Ptr, class Ptr2>
inline Ptr2 move(Ptr src, Ptr end, Ptr2 dest) {
using value_type = std::iterator_traits<Ptr>::value_type;
if constexpr (std::is_trivially_copyable_v<value_type>) {
return std::copy(src, end, dest);
} else {
while (src != end) {
*dest = std::move(*src);
++src; ++dest;
}
}
return dest;
}
EDIT: Kudos to zett42 for finding this related question: Contiguous iterator detection I can't explain how I missed it.
EDIT More: After going down many twisty little passages all the same, I discovered that Dinkum uses secret tags for iterators that are in with the in-crowd, e.g. _Really_trivial_ptr_iterator_tag. So prospects look dim.
My $0.02 worth: It was a beginner's mistake to make iterator_category an ad-hoc type rather than busting out the various traits, like "points_into_contiguous_memory," etc... Since random_access_iterator is an ad-hoc type denoted only with a tag, it cannot be subtyped without breaking legacy applications. So the committee is now kind of stuck. Time to start over, I say.
Oh well.