views:

168

answers:

4

When copying data from one range to another, you have to be careful if there's partial overlap between the source and destination ranges. If the beginning of the destination range overlaps the tail of the source range, a plain sequential copy will garble the data. The C run-time library has memmove in addition to memcopy to handle such overlap problems.

I assume std::copy works like memcopy, in that it doesn't pay any regard to overlap between the source and destination regions. If you try to shift objects "down" in a std::vector with std::copy, you'll corrupt the data. Is there an STL algorithm analogue of memmove to handle situations like this? Or should I roll my own with reverse iterators?

+5  A: 

preconditions for std::copy, prohibits an overlap

Prototype

template <class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last,
                    OutputIterator result);



Preconditions

     * [first, last) is a valid range.
     * result is not an iterator within the range [first, last).
     * There is enough space to hold all of the elements being copied. More
 formally, the requirement is that
 [result, result + (last - first)) is a
 valid range. [1]
Alon
That answers the question in the title. The remaining question is whether there's an analogue of `memmove` or if I have to roll my own.
Adrian McCarthy
That only prohibits an overlap with the start of the destination range. As John says, an overlap with the middle or end is allowed, and `std::copy_backward` allows an overlap with the start (but not the end).
Mike Seymour
+6  A: 

It doesn't handle overlapping ranges iff the beginning of the output range overlaps with the input range.

Fortunately, you can use std::copy_backward instead (which requires that you don't overlap the end of the output range with the input range).

John Feminella
`std::copy_backward` would be useful in trying to implement and analogue of `memmove`. I want to take the checking for overlap burden off of the caller.
Adrian McCarthy
A: 

It seems the most straight forward way would be to create a temporary vector of the range you want to copy:

std::vector copiedRange( srcVecIterBegin, srcVecIterEnd);
std::copy( copiedRange.begin(), copiedRange.end(), srcVecIterCopyLocIter);

You can wrap this in a templated function that should be ably to do an overlapped using any container/iterator type.

Doug T.
Yeah, but that might lead to a lot more copying than necessary. I'd rather right a function that tests for overlap and then uses the right copy technique to do it in place.
Adrian McCarthy
A: 

std::copy is mostly used with containers in which you normally don't move blocks, so overlap has not been an issue for me. If you want to move blocks of memory which can overlap, then memmove is still the way to go, especially as you are concerned with superfluous copies.

stefaanv