Consolidate overloads of copy()

This commit is contained in:
Andrei Alexandrescu 2019-03-27 22:28:59 -04:00
parent ba490f4d7b
commit 439b9a701b

View file

@ -366,58 +366,56 @@ Returns:
The unfilled part of target The unfilled part of target
*/ */
TargetRange copy(SourceRange, TargetRange)(SourceRange source, TargetRange target) TargetRange copy(SourceRange, TargetRange)(SourceRange source, TargetRange target)
if (areCopyCompatibleArrays!(SourceRange, TargetRange)) if (isInputRange!SourceRange && isOutputRange!(TargetRange, ElementType!SourceRange))
{ {
const tlen = target.length; static if (areCopyCompatibleArrays!(SourceRange, TargetRange))
const slen = source.length;
assert(tlen >= slen,
"Cannot copy a source range into a smaller target range.");
immutable overlaps = __ctfe || () @trusted {
return source.ptr < target.ptr + tlen &&
target.ptr < source.ptr + slen; }();
if (overlaps)
{ {
foreach (idx; 0 .. slen) const tlen = target.length;
target[idx] = source[idx]; const slen = source.length;
return target[slen .. tlen]; assert(tlen >= slen,
"Cannot copy a source range into a smaller target range.");
immutable overlaps = __ctfe || () @trusted {
return source.ptr < target.ptr + tlen &&
target.ptr < source.ptr + slen; }();
if (overlaps)
{
foreach (idx; 0 .. slen)
target[idx] = source[idx];
return target[slen .. tlen];
}
else
{
// Array specialization. This uses optimized memory copying
// routines under the hood and is about 10-20x faster than the
// generic implementation.
target[0 .. slen] = source[];
return target[slen .. $];
}
} }
else else
{ {
// Array specialization. This uses optimized memory copying // Specialize for 2 random access ranges.
// routines under the hood and is about 10-20x faster than the // Typically 2 random access ranges are faster iterated by common
// generic implementation. // index than by x.popFront(), y.popFront() pair
target[0 .. slen] = source[]; static if (isRandomAccessRange!SourceRange &&
return target[slen .. $]; hasLength!SourceRange &&
} hasSlicing!TargetRange &&
} isRandomAccessRange!TargetRange &&
hasLength!TargetRange)
/// ditto {
TargetRange copy(SourceRange, TargetRange)(SourceRange source, TargetRange target) auto len = source.length;
if (!areCopyCompatibleArrays!(SourceRange, TargetRange) && foreach (idx; 0 .. len)
isInputRange!SourceRange && target[idx] = source[idx];
isOutputRange!(TargetRange, ElementType!SourceRange)) return target[len .. target.length];
{ }
// Specialize for 2 random access ranges. else
// Typically 2 random access ranges are faster iterated by common {
// index than by x.popFront(), y.popFront() pair foreach (element; source)
static if (isRandomAccessRange!SourceRange && put(target, element);
hasLength!SourceRange && return target;
hasSlicing!TargetRange && }
isRandomAccessRange!TargetRange &&
hasLength!TargetRange)
{
auto len = source.length;
foreach (idx; 0 .. len)
target[idx] = source[idx];
return target[len .. target.length];
}
else
{
foreach (element; source)
put(target, element);
return target;
} }
} }