xref: /netbsd-src/external/gpl3/gcc/dist/libphobos/src/std/algorithm/mutation.d (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 // Written in the D programming language.
2 /**
3 This is a submodule of $(MREF std, algorithm).
4 It contains generic mutation algorithms.
5 
6 $(SCRIPT inhibitQuickIndex = 1;)
7 $(BOOKTABLE Cheat Sheet,
8 $(TR $(TH Function Name) $(TH Description))
9 $(T2 bringToFront,
10         If `a = [1, 2, 3]` and `b = [4, 5, 6, 7]`,
11         `bringToFront(a, b)` leaves `a = [4, 5, 6]` and
12         `b = [7, 1, 2, 3]`.)
13 $(T2 copy,
14         Copies a range to another. If
15         `a = [1, 2, 3]` and `b = new int[5]`, then `copy(a, b)`
16         leaves `b = [1, 2, 3, 0, 0]` and returns `b[3 .. $]`.)
17 $(T2 fill,
18         Fills a range with a pattern,
19         e.g., if `a = new int[3]`, then `fill(a, 4)`
20         leaves `a = [4, 4, 4]` and `fill(a, [3, 4])` leaves
21         `a = [3, 4, 3]`.)
22 $(T2 initializeAll,
23         If `a = [1.2, 3.4]`, then `initializeAll(a)` leaves
24         `a = [double.init, double.init]`.)
25 $(T2 move,
26         `move(a, b)` moves `a` into `b`. `move(a)` reads `a`
27         destructively when necessary.)
28 $(T2 moveEmplace,
29         Similar to `move` but assumes `target` is uninitialized.)
30 $(T2 moveAll,
31         Moves all elements from one range to another.)
32 $(T2 moveEmplaceAll,
33         Similar to `moveAll` but assumes all elements in `target` are uninitialized.)
34 $(T2 moveSome,
35         Moves as many elements as possible from one range to another.)
36 $(T2 moveEmplaceSome,
37         Similar to `moveSome` but assumes all elements in `target` are uninitialized.)
38 $(T2 remove,
39         Removes elements from a range in-place, and returns the shortened
40         range.)
41 $(T2 reverse,
42         If `a = [1, 2, 3]`, `reverse(a)` changes it to `[3, 2, 1]`.)
43 $(T2 strip,
44         Strips all leading and trailing elements equal to a value, or that
45         satisfy a predicate.
46         If `a = [1, 1, 0, 1, 1]`, then `strip(a, 1)` and
47         `strip!(e => e == 1)(a)` returns `[0]`.)
48 $(T2 stripLeft,
49         Strips all leading elements equal to a value, or that satisfy a
50         predicate.  If `a = [1, 1, 0, 1, 1]`, then `stripLeft(a, 1)` and
51         `stripLeft!(e => e == 1)(a)` returns `[0, 1, 1]`.)
52 $(T2 stripRight,
53         Strips all trailing elements equal to a value, or that satisfy a
54         predicate.
55         If `a = [1, 1, 0, 1, 1]`, then `stripRight(a, 1)` and
56         `stripRight!(e => e == 1)(a)` returns `[1, 1, 0]`.)
57 $(T2 swap,
58         Swaps two values.)
59 $(T2 swapAt,
60         Swaps two values by indices.)
61 $(T2 swapRanges,
62         Swaps all elements of two ranges.)
63 $(T2 uninitializedFill,
64         Fills a range (assumed uninitialized) with a value.)
65 )
66 
67 Copyright: Andrei Alexandrescu 2008-.
68 
69 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
70 
71 Authors: $(HTTP erdani.com, Andrei Alexandrescu)
72 
73 Source: $(PHOBOSSRC std/algorithm/mutation.d)
74 
75 Macros:
76 T2=$(TR $(TDNW $(LREF $1)) $(TD $+))
77  */
78 module std.algorithm.mutation;
79 
80 import std.range.primitives;
81 import std.traits : isArray, isAssignable, isBlitAssignable, isNarrowString,
82        Unqual, isSomeChar, isMutable;
83 import std.meta : allSatisfy;
84 import std.typecons : tuple, Tuple;
85 
86 // bringToFront
87 /**
88 `bringToFront` takes two ranges `front` and `back`, which may
89 be of different types. Considering the concatenation of `front` and
90 `back` one unified range, `bringToFront` rotates that unified
91 range such that all elements in `back` are brought to the beginning
92 of the unified range. The relative ordering of elements in `front`
93 and `back`, respectively, remains unchanged.
94 
95 The `bringToFront` function treats strings at the code unit
96 level and it is not concerned with Unicode character integrity.
97 `bringToFront` is designed as a function for moving elements
98 in ranges, not as a string function.
99 
100 Performs $(BIGOH max(front.length, back.length)) evaluations of $(D
101 swap).
102 
103 The `bringToFront` function can rotate elements in one buffer left or right, swap
104 buffers of equal length, and even move elements across disjoint
105 buffers of different types and different lengths.
106 
107 Preconditions:
108 
109 Either `front` and `back` are disjoint, or `back` is
110 reachable from `front` and `front` is not reachable from $(D
111 back).
112 
113 Params:
114     front = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
115     back = a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
116 
117 Returns:
118     The number of elements brought to the front, i.e., the length of `back`.
119 
120 See_Also:
121     $(LINK2 http://en.cppreference.com/w/cpp/algorithm/rotate, STL's `rotate`)
122 */
123 size_t bringToFront(InputRange, ForwardRange)(InputRange front, ForwardRange back)
124 if (isInputRange!InputRange && isForwardRange!ForwardRange)
125 {
126     import std.string : representation;
127 
128     static if (isNarrowString!InputRange)
129     {
130         auto frontW = representation(front);
131     }
132     else
133     {
134         alias frontW = front;
135     }
136     static if (isNarrowString!ForwardRange)
137     {
138         auto backW = representation(back);
139     }
140     else
141     {
142         alias backW = back;
143     }
144 
145     return bringToFrontImpl(frontW, backW);
146 }
147 
148 /**
149 The simplest use of `bringToFront` is for rotating elements in a
150 buffer. For example:
151 */
152 @safe unittest
153 {
154     auto arr = [4, 5, 6, 7, 1, 2, 3];
155     auto p = bringToFront(arr[0 .. 4], arr[4 .. $]);
156     assert(p == arr.length - 4);
157     assert(arr == [ 1, 2, 3, 4, 5, 6, 7 ]);
158 }
159 
160 /**
161 The `front` range may actually "step over" the `back`
162 range. This is very useful with forward ranges that cannot compute
163 comfortably right-bounded subranges like `arr[0 .. 4]` above. In
164 the example below, `r2` is a right subrange of `r1`.
165 */
166 @safe unittest
167 {
168     import std.algorithm.comparison : equal;
169     import std.container : SList;
170     import std.range.primitives : popFrontN;
171 
172     auto list = SList!(int)(4, 5, 6, 7, 1, 2, 3);
173     auto r1 = list[];
174     auto r2 = list[]; popFrontN(r2, 4);
175     assert(equal(r2, [ 1, 2, 3 ]));
176     bringToFront(r1, r2);
177     assert(equal(list[], [ 1, 2, 3, 4, 5, 6, 7 ]));
178 }
179 
180 /**
181 Elements can be swapped across ranges of different types:
182 */
183 @safe unittest
184 {
185     import std.algorithm.comparison : equal;
186     import std.container : SList;
187 
188     auto list = SList!(int)(4, 5, 6, 7);
189     auto vec = [ 1, 2, 3 ];
190     bringToFront(list[], vec);
191     assert(equal(list[], [ 1, 2, 3, 4 ]));
192     assert(equal(vec, [ 5, 6, 7 ]));
193 }
194 
195 /**
196 Unicode integrity is not preserved:
197 */
198 @safe unittest
199 {
200     import std.string : representation;
201     auto ar = representation("a".dup);
202     auto br = representation("ç".dup);
203 
204     bringToFront(ar, br);
205 
206     auto a = cast(char[]) ar;
207     auto b = cast(char[]) br;
208 
209     // Illegal UTF-8
210     assert(a == "\303");
211     // Illegal UTF-8
212     assert(b == "\247a");
213 }
214 
215 private size_t bringToFrontImpl(InputRange, ForwardRange)(InputRange front, ForwardRange back)
216 if (isInputRange!InputRange && isForwardRange!ForwardRange)
217 {
218     import std.array : sameHead;
219     import std.range : take, Take;
220     enum bool sameHeadExists = is(typeof(front.sameHead(back)));
221     size_t result;
222 
223     for (bool semidone; !front.empty && !back.empty; )
224     {
225         static if (sameHeadExists)
226         {
227             if (front.sameHead(back)) break; // shortcut
228         }
229         // Swap elements until front and/or back ends.
230         auto back0 = back.save;
231         size_t nswaps;
232         do
233         {
234             static if (sameHeadExists)
235             {
236                 // Detect the stepping-over condition.
237                 if (front.sameHead(back0)) back0 = back.save;
238             }
239             swapFront(front, back);
240             ++nswaps;
241             front.popFront();
242             back.popFront();
243         }
244         while (!front.empty && !back.empty);
245 
246         if (!semidone) result += nswaps;
247 
248         // Now deal with the remaining elements.
249         if (back.empty)
250         {
251             if (front.empty) break;
252             // Right side was shorter, which means that we've brought
253             // all the back elements to the front.
254             semidone = true;
255             // Next pass: bringToFront(front, back0) to adjust the rest.
256             back = back0;
257         }
258         else
259         {
260             assert(front.empty, "Expected front to be empty");
261             // Left side was shorter. Let's step into the back.
262             static if (is(InputRange == Take!ForwardRange))
263             {
264                 front = take(back0, nswaps);
265             }
266             else
267             {
268                 immutable subresult = bringToFront(take(back0, nswaps),
269                                                    back);
270                 if (!semidone) result += subresult;
271                 break; // done
272             }
273         }
274     }
275     return result;
276 }
277 
278 @safe unittest
279 {
280     import std.algorithm.comparison : equal;
281     import std.conv : text;
282     import std.random : Random = Xorshift, uniform;
283 
284     // a more elaborate test
285     {
286         auto rnd = Random(123_456_789);
287         int[] a = new int[uniform(100, 200, rnd)];
288         int[] b = new int[uniform(100, 200, rnd)];
289         foreach (ref e; a) e = uniform(-100, 100, rnd);
290         foreach (ref e; b) e = uniform(-100, 100, rnd);
291         int[] c = a ~ b;
292         // writeln("a= ", a);
293         // writeln("b= ", b);
294         auto n = bringToFront(c[0 .. a.length], c[a.length .. $]);
295         //writeln("c= ", c);
296         assert(n == b.length);
297         assert(c == b ~ a, text(c, "\n", a, "\n", b));
298     }
299     // different types, moveFront, no sameHead
300     {
R(T)301         static struct R(T)
302         {
303             T[] data;
304             size_t i;
305             @property
306             {
307                 R save() { return this; }
308                 bool empty() { return i >= data.length; }
309                 T front() { return data[i]; }
310                 T front(real e) { return data[i] = cast(T) e; }
311             }
312             void popFront() { ++i; }
313         }
314         auto a = R!int([1, 2, 3, 4, 5]);
315         auto b = R!real([6, 7, 8, 9]);
316         auto n = bringToFront(a, b);
317         assert(n == 4);
318         assert(a.data == [6, 7, 8, 9, 1]);
319         assert(b.data == [2, 3, 4, 5]);
320     }
321     // front steps over back
322     {
323         int[] arr, r1, r2;
324 
325         // back is shorter
326         arr = [4, 5, 6, 7, 1, 2, 3];
327         r1 = arr;
328         r2 = arr[4 .. $];
329         bringToFront(r1, r2) == 3 || assert(0);
330         assert(equal(arr, [1, 2, 3, 4, 5, 6, 7]));
331 
332         // front is shorter
333         arr = [5, 6, 7, 1, 2, 3, 4];
334         r1 = arr;
335         r2 = arr[3 .. $];
336         bringToFront(r1, r2) == 4 || assert(0);
337         assert(equal(arr, [1, 2, 3, 4, 5, 6, 7]));
338     }
339 
340     // https://issues.dlang.org/show_bug.cgi?id=16959
341     auto arr = ['4', '5', '6', '7', '1', '2', '3'];
342     auto p = bringToFront(arr[0 .. 4], arr[4 .. $]);
343 
344     assert(p == arr.length - 4);
345     assert(arr == ['1', '2', '3', '4', '5', '6', '7']);
346 }
347 
348 // Tests if types are arrays and support slice assign.
349 private enum bool areCopyCompatibleArrays(T1, T2) =
350     isArray!T1 && isArray!T2 && is(typeof(T2.init[] = T1.init[]));
351 
352 // copy
353 /**
354 Copies the content of `source` into `target` and returns the
355 remaining (unfilled) part of `target`.
356 
357 Preconditions: `target` shall have enough room to accommodate
358 the entirety of `source`.
359 
360 Params:
361     source = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
362     target = an output range
363 
364 Returns:
365     The unfilled part of target
366  */
367 TargetRange copy(SourceRange, TargetRange)(SourceRange source, TargetRange target)
368 if (isInputRange!SourceRange && isOutputRange!(TargetRange, ElementType!SourceRange))
369 {
370     static if (areCopyCompatibleArrays!(SourceRange, TargetRange))
371     {
372         const tlen = target.length;
373         const slen = source.length;
374         assert(tlen >= slen,
375                 "Cannot copy a source range into a smaller target range.");
376 
377         immutable overlaps = () @trusted {
378             return source.ptr < target.ptr + tlen &&
379                 target.ptr < source.ptr + slen; }();
380 
381         if (overlaps)
382         {
383             if (source.ptr < target.ptr)
384             {
385                 foreach_reverse (idx; 0 .. slen)
386                     target[idx] = source[idx];
387             }
388             else
389             {
390                 foreach (idx; 0 .. slen)
391                     target[idx] = source[idx];
392             }
393             return target[slen .. tlen];
394         }
395         else
396         {
397             // Array specialization.  This uses optimized memory copying
398             // routines under the hood and is about 10-20x faster than the
399             // generic implementation.
400             target[0 .. slen] = source[];
401             return target[slen .. $];
402         }
403     }
404     else
405     {
406         // Specialize for 2 random access ranges.
407         // Typically 2 random access ranges are faster iterated by common
408         // index than by x.popFront(), y.popFront() pair
409         static if (isRandomAccessRange!SourceRange &&
410                 hasLength!SourceRange &&
411                 hasSlicing!TargetRange &&
412                 isRandomAccessRange!TargetRange &&
413                 hasLength!TargetRange)
414         {
415             auto len = source.length;
416             foreach (idx; 0 .. len)
417                 target[idx] = source[idx];
418             return target[len .. target.length];
419         }
420         else
421         {
422             foreach (element; source)
423                 put(target, element);
424             return target;
425         }
426     }
427 }
428 
429 ///
430 @safe unittest
431 {
432     int[] a = [ 1, 5 ];
433     int[] b = [ 9, 8 ];
434     int[] buf = new int[](a.length + b.length + 10);
435     auto rem = a.copy(buf);    // copy a into buf
436     rem = b.copy(rem);         // copy b into remainder of buf
437     assert(buf[0 .. a.length + b.length] == [1, 5, 9, 8]);
438     assert(rem.length == 10);   // unused slots in buf
439 }
440 
441 /**
442 As long as the target range elements support assignment from source
443 range elements, different types of ranges are accepted:
444 */
445 @safe unittest
446 {
447     float[] src = [ 1.0f, 5 ];
448     double[] dest = new double[src.length];
449     src.copy(dest);
450 }
451 
452 /**
453 To _copy at most `n` elements from a range, you may want to use
454 $(REF take, std,range):
455 */
456 @safe unittest
457 {
458     import std.range;
459     int[] src = [ 1, 5, 8, 9, 10 ];
460     auto dest = new int[](3);
461     src.take(dest.length).copy(dest);
462     assert(dest == [ 1, 5, 8 ]);
463 }
464 
465 /**
466 To _copy just those elements from a range that satisfy a predicate,
467 use $(LREF filter):
468 */
469 @safe unittest
470 {
471     import std.algorithm.iteration : filter;
472     int[] src = [ 1, 5, 8, 9, 10, 1, 2, 0 ];
473     auto dest = new int[src.length];
474     auto rem = src
475         .filter!(a => (a & 1) == 1)
476         .copy(dest);
477     assert(dest[0 .. $ - rem.length] == [ 1, 5, 9, 1 ]);
478 }
479 
480 /**
481 $(REF retro, std,range) can be used to achieve behavior similar to
482 $(LINK2 http://en.cppreference.com/w/cpp/algorithm/copy_backward, STL's `copy_backward`'):
483 */
484 @safe unittest
485 {
486     import std.algorithm, std.range;
487     int[] src = [1, 2, 4];
488     int[] dest = [0, 0, 0, 0, 0];
489     src.retro.copy(dest.retro);
490     assert(dest == [0, 0, 1, 2, 4]);
491 }
492 
493 // Test CTFE copy.
494 @safe unittest
495 {
496     enum c = copy([1,2,3], [4,5,6,7]);
497     assert(c == [7]);
498 }
499 
500 
501 @safe unittest
502 {
503     import std.algorithm.iteration : filter;
504 
505     {
506         int[] a = [ 1, 5 ];
507         int[] b = [ 9, 8 ];
508         auto e = copy(filter!("a > 1")(a), b);
509         assert(b[0] == 5 && e.length == 1);
510     }
511 
512     {
513         int[] a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
514         copy(a[5 .. 10], a[4 .. 9]);
515         assert(a[4 .. 9] == [6, 7, 8, 9, 10]);
516     }
517 
518     // https://issues.dlang.org/show_bug.cgi?id=21724
519     {
520         int[] a = [1, 2, 3, 4];
521         copy(a[0 .. 2], a[1 .. 3]);
522         assert(a == [1, 1, 2, 4]);
523     }
524 
525     // https://issues.dlang.org/show_bug.cgi?id=7898
526     {
527         enum v =
528         {
529             import std.algorithm;
530             int[] arr1 = [10, 20, 30, 40, 50];
531             int[] arr2 = arr1.dup;
532             copy(arr1, arr2);
533             return 35;
534         }();
535         assert(v == 35);
536     }
537 }
538 
539 // https://issues.dlang.org/show_bug.cgi?id=13650
540 @safe unittest
541 {
542     import std.meta : AliasSeq;
543     static foreach (Char; AliasSeq!(char, wchar, dchar))
544     {{
545         Char[3] a1 = "123";
546         Char[6] a2 = "456789";
547         assert(copy(a1[], a2[]) is a2[3..$]);
548         assert(a1[] == "123");
549         assert(a2[] == "123789");
550     }}
551 }
552 
553 // https://issues.dlang.org/show_bug.cgi?id=18804
554 @safe unittest
555 {
556     static struct NullSink
557     {
putNullSink558         void put(E)(E) {}
559     }
560     int line = 0;
561     struct R
562     {
563         int front;
emptyR564         @property bool empty() { return line == 1; }
popFrontR565         void popFront() { line = 1; }
566     }
567     R r;
568     copy(r, NullSink());
569     assert(line == 1);
570 }
571 
572 /**
573 Assigns `value` to each element of input range `range`.
574 
575 Alternatively, instead of using a single `value` to fill the `range`,
576 a `filter` $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
577 can be provided. The length of `filler` and `range` do not need to match, but
578 `filler` must not be empty.
579 
580 Params:
581         range = An
582                 $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
583                 that exposes references to its elements and has assignable
584                 elements
585         value = Assigned to each element of range
586         filler = A
587                 $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
588                 representing the _fill pattern.
589 
590 Throws: If `filler` is empty.
591 
592 See_Also:
593         $(LREF uninitializedFill)
594         $(LREF initializeAll)
595  */
596 void fill(Range, Value)(auto ref Range range, auto ref Value value)
597 if ((isInputRange!Range && is(typeof(range.front = value)) ||
598     isSomeChar!Value && is(typeof(range[] = value))))
599 {
600     alias T = ElementType!Range;
601 
602     static if (is(typeof(range[] = value)))
603     {
604         range[] = value;
605     }
606     else static if (is(typeof(range[] = T(value))))
607     {
608         range[] = T(value);
609     }
610     else
611     {
612         for ( ; !range.empty; range.popFront() )
613         {
614             range.front = value;
615         }
616     }
617 }
618 
619 ///
620 @safe unittest
621 {
622     int[] a = [ 1, 2, 3, 4 ];
623     fill(a, 5);
624     assert(a == [ 5, 5, 5, 5 ]);
625 }
626 
627 // test fallback on mutable narrow strings
628 // https://issues.dlang.org/show_bug.cgi?id=16342
629 @safe unittest
630 {
631     char[] chars = ['a', 'b'];
632     fill(chars, 'c');
633     assert(chars == "cc");
634 
635     char[2] chars2 = ['a', 'b'];
636     fill(chars2, 'c');
637     assert(chars2 == "cc");
638 
639     wchar[] wchars = ['a', 'b'];
640     fill(wchars, wchar('c'));
641     assert(wchars == "cc"w);
642 
643     dchar[] dchars = ['a', 'b'];
644     fill(dchars, dchar('c'));
645     assert(dchars == "cc"d);
646 }
647 
648 @nogc @safe unittest
649 {
650     const(char)[] chars;
651     assert(chars.length == 0);
652     static assert(!__traits(compiles, fill(chars, 'c')));
653     wstring wchars;
654     assert(wchars.length == 0);
655     static assert(!__traits(compiles, fill(wchars, wchar('c'))));
656 }
657 
658 @nogc @safe unittest
659 {
660     char[] chars;
661     fill(chars, 'c');
662     assert(chars == ""c);
663 }
664 
665 @safe unittest
666 {
667     shared(char)[] chrs = ['r'];
668     fill(chrs, 'c');
669     assert(chrs == [shared(char)('c')]);
670 }
671 
672 @nogc @safe unittest
673 {
Str(size_t len)674     struct Str(size_t len)
675     {
676         private char[len] _data;
677         void opIndexAssign(char value) @safe @nogc
678         {_data[] = value;}
679     }
680     Str!2 str;
681     str.fill(':');
682     assert(str._data == "::");
683 }
684 
685 @safe unittest
686 {
687     char[] chars = ['a','b','c','d'];
688     chars[1 .. 3].fill(':');
689     assert(chars == "a::d");
690 }
691 // end https://issues.dlang.org/show_bug.cgi?id=16342
692 
693 @safe unittest
694 {
695     import std.conv : text;
696     import std.internal.test.dummyrange;
697 
698     int[] a = [ 1, 2, 3 ];
699     fill(a, 6);
700     assert(a == [ 6, 6, 6 ], text(a));
701 
fun0()702     void fun0()
703     {
704         foreach (i; 0 .. 1000)
705         {
706             foreach (ref e; a) e = 6;
707         }
708     }
fun1()709     void fun1() { foreach (i; 0 .. 1000) fill(a, 6); }
710 
711     // fill should accept InputRange
712     alias InputRange = DummyRange!(ReturnBy.Reference, Length.No, RangeType.Input);
713     enum filler = uint.max;
714     InputRange range;
715     fill(range, filler);
716     foreach (value; range.arr)
717         assert(value == filler);
718 }
719 
720 @safe unittest
721 {
722     //ER8638_1 IS_NOT self assignable
723     static struct ER8638_1
724     {
opAssignER8638_1725         void opAssign(int){}
726     }
727 
728     //ER8638_1 IS self assignable
729     static struct ER8638_2
730     {
opAssign(ER8638_2)731         void opAssign(ER8638_2){}
opAssign(int)732         void opAssign(int){}
733     }
734 
735     auto er8638_1 = new ER8638_1[](10);
736     auto er8638_2 = new ER8638_2[](10);
737     er8638_1.fill(5); //generic case
738     er8638_2.fill(5); //opSlice(T.init) case
739 }
740 
741 @safe unittest
742 {
743     {
744         int[] a = [1, 2, 3];
745         immutable(int) b = 0;
746         a.fill(b);
747         assert(a == [0, 0, 0]);
748     }
749     {
750         double[] a = [1, 2, 3];
751         immutable(int) b = 0;
752         a.fill(b);
753         assert(a == [0, 0, 0]);
754     }
755 }
756 
757 /// ditto
758 void fill(InputRange, ForwardRange)(InputRange range, ForwardRange filler)
759 if (isInputRange!InputRange
760     && (isForwardRange!ForwardRange
761     || (isInputRange!ForwardRange && isInfinite!ForwardRange))
762     && is(typeof(InputRange.init.front = ForwardRange.init.front)))
763 {
764     static if (isInfinite!ForwardRange)
765     {
766         //ForwardRange is infinite, no need for bounds checking or saving
767         static if (hasSlicing!ForwardRange && hasLength!InputRange
768             && is(typeof(filler[0 .. range.length])))
769         {
770             copy(filler[0 .. range.length], range);
771         }
772         else
773         {
774             //manual feed
775             for ( ; !range.empty; range.popFront(), filler.popFront())
776             {
777                 range.front = filler.front;
778             }
779         }
780     }
781     else
782     {
783         import std.exception : enforce;
784 
785         enforce(!filler.empty, "Cannot fill range with an empty filler");
786 
787         static if (hasLength!InputRange && hasLength!ForwardRange
788             && is(typeof(range.length > filler.length)))
789         {
790             //Case we have access to length
791             immutable len = filler.length;
792             //Start by bulk copies
793             while (range.length > len)
794             {
795                 range = copy(filler.save, range);
796             }
797 
798             //and finally fill the partial range. No need to save here.
799             static if (hasSlicing!ForwardRange && is(typeof(filler[0 .. range.length])))
800             {
801                 //use a quick copy
802                 auto len2 = range.length;
803                 range = copy(filler[0 .. len2], range);
804             }
805             else
806             {
807                 //iterate. No need to check filler, it's length is longer than range's
808                 for (; !range.empty; range.popFront(), filler.popFront())
809                 {
810                     range.front = filler.front;
811                 }
812             }
813         }
814         else
815         {
816             //Most basic case.
817             auto bck = filler.save;
818             for (; !range.empty; range.popFront(), filler.popFront())
819             {
820                 if (filler.empty) filler = bck.save;
821                 range.front = filler.front;
822             }
823         }
824     }
825 }
826 
827 ///
828 @safe unittest
829 {
830     int[] a = [ 1, 2, 3, 4, 5 ];
831     int[] b = [ 8, 9 ];
832     fill(a, b);
833     assert(a == [ 8, 9, 8, 9, 8 ]);
834 }
835 
836 @safe unittest
837 {
838     import std.exception : assertThrown;
839     import std.internal.test.dummyrange;
840 
841     int[] a = [ 1, 2, 3, 4, 5 ];
842     int[] b = [1, 2];
843     fill(a, b);
844     assert(a == [ 1, 2, 1, 2, 1 ]);
845 
846     // fill should accept InputRange
847     alias InputRange = DummyRange!(ReturnBy.Reference, Length.No, RangeType.Input);
848     InputRange range;
849     fill(range,[1,2]);
850     foreach (i,value;range.arr)
851     assert(value == (i%2 == 0?1:2));
852 
853     //test with a input being a "reference forward" range
854     fill(a, new ReferenceForwardRange!int([8, 9]));
855     assert(a == [8, 9, 8, 9, 8]);
856 
857     //test with a input being an "infinite input" range
858     fill(a, new ReferenceInfiniteInputRange!int());
859     assert(a == [0, 1, 2, 3, 4]);
860 
861     //empty filler test
862     assertThrown(fill(a, a[$..$]));
863 }
864 
865 /**
866 Initializes all elements of `range` with their `.init` value.
867 Assumes that the elements of the range are uninitialized.
868 
869 This function is unavailable if `T` is a `struct` and  `T.this()` is annotated
870 with `@disable`.
871 
872 Params:
873         range = An
874                 $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
875                 that exposes references to its elements and has assignable
876                 elements
877 
878 See_Also:
879         $(LREF fill)
880         $(LREF uninitializedFill)
881  */
882 void initializeAll(Range)(Range range)
883 if (isInputRange!Range && hasLvalueElements!Range && hasAssignableElements!Range
884     && __traits(compiles, { static ElementType!Range _; }))
885 {
886     import core.stdc.string : memset, memcpy;
887     import std.traits : hasElaborateAssign, isDynamicArray;
888 
889     alias T = ElementType!Range;
890     static if (hasElaborateAssign!T)
891     {
892         import std.algorithm.internal : addressOf;
893         //Elaborate opAssign. Must go the memcpy/memset road.
894         static if (!__traits(isZeroInit, T))
895         {
896             for ( ; !range.empty ; range.popFront() )
897             {
898                 import core.internal.lifetime : emplaceInitializer;
899                 emplaceInitializer(range.front);
900             }
901         }
902         else
903             static if (isDynamicArray!Range)
904                 memset(range.ptr, 0, range.length * T.sizeof);
905             else
906                 for ( ; !range.empty ; range.popFront() )
907                     memset(addressOf(range.front), 0, T.sizeof);
908     }
909     else
910         fill(range, T.init);
911 }
912 
913 /// ditto
914 void initializeAll(Range)(Range range)
915 if (is(Range == char[]) || is(Range == wchar[]))
916 {
917     alias T = ElementEncodingType!Range;
918     range[] = T.init;
919 }
920 
921 ///
922 @system unittest
923 {
924     import core.stdc.stdlib : malloc, free;
925 
926     struct S
927     {
928         int a = 10;
929     }
930 
931     auto s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5];
932     initializeAll(s);
933     assert(s == [S(10), S(10), S(10), S(10), S(10)]);
934 
935     scope(exit) free(s.ptr);
936 }
937 
938 @system unittest
939 {
940     import std.algorithm.iteration : filter;
941     import std.meta : AliasSeq;
942     import std.traits : hasElaborateAssign;
943 
944     //Test strings:
945     //Must work on narrow strings.
946     //Must reject const
947     char[3] a = void;
948     a[].initializeAll();
949     assert(a[] == [char.init, char.init, char.init]);
950     string s;
951     assert(!__traits(compiles, s.initializeAll()));
952     assert(!__traits(compiles, s.initializeAll()));
953     assert(s.empty);
954 
955     //Note: Cannot call uninitializedFill on narrow strings
956 
957     enum e {e1, e2}
958     e[3] b1 = void;
959     b1[].initializeAll();
960     assert(b1[] == [e.e1, e.e1, e.e1]);
961     e[3] b2 = void;
962     b2[].uninitializedFill(e.e2);
963     assert(b2[] == [e.e2, e.e2, e.e2]);
964 
965     static struct S1
966     {
967         int i;
968     }
969     static struct S2
970     {
971         int i = 1;
972     }
973     static struct S3
974     {
975         int i;
thisS3976         this(this){}
977     }
978     static struct S4
979     {
980         int i = 1;
this(this)981         this(this){}
982     }
983     static assert(!hasElaborateAssign!S1);
984     static assert(!hasElaborateAssign!S2);
985     static assert( hasElaborateAssign!S3);
986     static assert( hasElaborateAssign!S4);
987     assert(!typeid(S1).initializer().ptr);
988     assert( typeid(S2).initializer().ptr);
989     assert(!typeid(S3).initializer().ptr);
990     assert( typeid(S4).initializer().ptr);
991 
992     static foreach (S; AliasSeq!(S1, S2, S3, S4))
993     {
994         //initializeAll
995         {
996             //Array
997             S[3] ss1 = void;
998             ss1[].initializeAll();
999             assert(ss1[] == [S.init, S.init, S.init]);
1000 
1001             //Not array
1002             S[3] ss2 = void;
1003             auto sf = ss2[].filter!"true"();
1004 
1005             sf.initializeAll();
1006             assert(ss2[] == [S.init, S.init, S.init]);
1007         }
1008         //uninitializedFill
1009         {
1010             //Array
1011             S[3] ss1 = void;
1012             ss1[].uninitializedFill(S(2));
1013             assert(ss1[] == [S(2), S(2), S(2)]);
1014 
1015             //Not array
1016             S[3] ss2 = void;
1017             auto sf = ss2[].filter!"true"();
1018             sf.uninitializedFill(S(2));
1019             assert(ss2[] == [S(2), S(2), S(2)]);
1020         }
1021     }
1022 }
1023 
1024 // test that initializeAll works for arrays of static arrays of structs with
1025 // elaborate assigns.
1026 @system unittest
1027 {
1028     struct Int {
~thisInt1029         ~this() {}
1030         int x = 3;
1031     }
1032     Int[2] xs = [Int(1), Int(2)];
1033     struct R {
1034         bool done;
emptyR1035         bool empty() { return done; }
frontR1036         ref Int[2] front() { return xs; }
popFrontR1037         void popFront() { done = true; }
1038     }
1039     initializeAll(R());
1040     assert(xs[0].x == 3);
1041     assert(xs[1].x == 3);
1042 }
1043 
1044 // https://issues.dlang.org/show_bug.cgi?id=22105
1045 @system unittest
1046 {
1047     struct NoDefaultCtor
1048     {
1049         @disable this();
1050     }
1051 
1052     NoDefaultCtor[1] array = void;
1053     static assert(!__traits(compiles, array[].initializeAll));
1054 }
1055 
1056 // move
1057 /**
1058 Moves `source` into `target`, via a destructive copy when necessary.
1059 
1060 If `T` is a struct with a destructor or postblit defined, source is reset
1061 to its `.init` value after it is moved into target, otherwise it is
1062 left unchanged.
1063 
1064 Preconditions:
1065 If source has internal pointers that point to itself and doesn't define
1066 opPostMove, it cannot be moved, and will trigger an assertion failure.
1067 
1068 Params:
1069     source = Data to copy.
1070     target = Where to copy into. The destructor, if any, is invoked before the
1071         copy is performed.
1072 */
move(T)1073 void move(T)(ref T source, ref T target)
1074 {
1075     moveImpl(target, source);
1076 }
1077 
1078 /// For non-struct types, `move` just performs `target = source`:
1079 @safe unittest
1080 {
1081     Object obj1 = new Object;
1082     Object obj2 = obj1;
1083     Object obj3;
1084 
1085     move(obj2, obj3);
1086     assert(obj3 is obj1);
1087     // obj2 unchanged
1088     assert(obj2 is obj1);
1089 }
1090 
1091 ///
1092 pure nothrow @safe @nogc unittest
1093 {
1094     // Structs without destructors are simply copied
1095     struct S1
1096     {
1097         int a = 1;
1098         int b = 2;
1099     }
1100     S1 s11 = { 10, 11 };
1101     S1 s12;
1102 
1103     move(s11, s12);
1104 
1105     assert(s12 == S1(10, 11));
1106     assert(s11 == s12);
1107 
1108     // But structs with destructors or postblits are reset to their .init value
1109     // after copying to the target.
1110     struct S2
1111     {
1112         int a = 1;
1113         int b = 2;
1114 
~thisS21115         ~this() pure nothrow @safe @nogc { }
1116     }
1117     S2 s21 = { 3, 4 };
1118     S2 s22;
1119 
1120     move(s21, s22);
1121 
1122     assert(s21 == S2(1, 2));
1123     assert(s22 == S2(3, 4));
1124 }
1125 
1126 @safe unittest
1127 {
1128     import std.exception : assertCTFEable;
1129     import std.traits;
1130 
1131     assertCTFEable!((){
1132         Object obj1 = new Object;
1133         Object obj2 = obj1;
1134         Object obj3;
1135         move(obj2, obj3);
1136         assert(obj3 is obj1);
1137 
1138         static struct S1 { int a = 1, b = 2; }
1139         S1 s11 = { 10, 11 };
1140         S1 s12;
1141         move(s11, s12);
1142         assert(s11.a == 10 && s11.b == 11 && s12.a == 10 && s12.b == 11);
1143 
1144         static struct S2 { int a = 1; int * b; }
1145         S2 s21 = { 10, null };
1146         s21.b = new int;
1147         S2 s22;
1148         move(s21, s22);
1149         assert(s21 == s22);
1150     });
1151     // https://issues.dlang.org/show_bug.cgi?id=5661 test(1)
1152     static struct S3
1153     {
~thisS3::X1154         static struct X { int n = 0; ~this(){n = 0;} }
1155         X x;
1156     }
1157     static assert(hasElaborateDestructor!S3);
1158     S3 s31, s32;
1159     s31.x.n = 1;
1160     move(s31, s32);
1161     assert(s31.x.n == 0);
1162     assert(s32.x.n == 1);
1163 
1164     // https://issues.dlang.org/show_bug.cgi?id=5661 test(2)
1165     static struct S4
1166     {
thisS4::X1167         static struct X { int n = 0; this(this){n = 0;} }
1168         X x;
1169     }
1170     static assert(hasElaborateCopyConstructor!S4);
1171     S4 s41, s42;
1172     s41.x.n = 1;
1173     move(s41, s42);
1174     assert(s41.x.n == 0);
1175     assert(s42.x.n == 1);
1176 
1177     // https://issues.dlang.org/show_bug.cgi?id=13990 test
1178     class S5;
1179 
1180     S5 s51;
1181     S5 s52 = s51;
1182     S5 s53;
1183     move(s52, s53);
1184     assert(s53 is s51);
1185 }
1186 
1187 /// Ditto
move(T)1188 T move(T)(return scope ref T source)
1189 {
1190     return moveImpl(source);
1191 }
1192 
1193 /// Non-copyable structs can still be moved:
1194 pure nothrow @safe @nogc unittest
1195 {
1196     struct S
1197     {
1198         int a = 1;
1199         @disable this(this);
~thisS1200         ~this() pure nothrow @safe @nogc {}
1201     }
1202     S s1;
1203     s1.a = 2;
1204     S s2 = move(s1);
1205     assert(s1.a == 1);
1206     assert(s2.a == 2);
1207 }
1208 
1209 /// `opPostMove` will be called if defined:
1210 pure nothrow @safe @nogc unittest
1211 {
1212     struct S
1213     {
1214         int a;
opPostMoveS1215         void opPostMove(const ref S old)
1216         {
1217             assert(a == old.a);
1218             a++;
1219         }
1220     }
1221     S s1;
1222     s1.a = 41;
1223     S s2 = move(s1);
1224     assert(s2.a == 42);
1225 }
1226 
1227 // https://issues.dlang.org/show_bug.cgi?id=20869
1228 // `move` should propagate the attributes of `opPostMove`
1229 @system unittest
1230 {
1231     static struct S
1232     {
opPostMoveS1233         void opPostMove(const ref S old) nothrow @system
1234         {
1235             __gshared int i;
1236             new int(i++); // Force @gc impure @system
1237         }
1238     }
1239 
1240     alias T = void function() @system nothrow;
1241     static assert(is(typeof({ S s; move(s); }) == T));
1242     static assert(is(typeof({ S s; move(s, s); }) == T));
1243 }
1244 
moveImpl(T)1245 private void moveImpl(T)(ref scope T target, ref return scope T source)
1246 {
1247     import std.traits : hasElaborateDestructor;
1248 
1249     static if (is(T == struct))
1250     {
1251         //  Unsafe when compiling without -dip1000
1252         if ((() @trusted => &source == &target)()) return;
1253 
1254         // Destroy target before overwriting it
1255         static if (hasElaborateDestructor!T) target.__xdtor();
1256     }
1257     // move and emplace source into target
1258     moveEmplaceImpl(target, source);
1259 }
1260 
moveImpl(T)1261 private T moveImpl(T)(ref return scope T source)
1262 {
1263     // Properly infer safety from moveEmplaceImpl as the implementation below
1264     // might void-initialize pointers in result and hence needs to be @trusted
1265     if (false) moveEmplaceImpl(source, source);
1266 
1267     return trustedMoveImpl(source);
1268 }
1269 
trustedMoveImpl(T)1270 private T trustedMoveImpl(T)(ref return scope T source) @trusted
1271 {
1272     T result = void;
1273     moveEmplaceImpl(result, source);
1274     return result;
1275 }
1276 
1277 @safe unittest
1278 {
1279     import std.exception : assertCTFEable;
1280     import std.traits;
1281 
1282     assertCTFEable!((){
1283         Object obj1 = new Object;
1284         Object obj2 = obj1;
1285         Object obj3 = move(obj2);
1286         assert(obj3 is obj1);
1287 
1288         static struct S1 { int a = 1, b = 2; }
1289         S1 s11 = { 10, 11 };
1290         S1 s12 = move(s11);
1291         assert(s11.a == 10 && s11.b == 11 && s12.a == 10 && s12.b == 11);
1292 
1293         static struct S2 { int a = 1; int * b; }
1294         S2 s21 = { 10, null };
1295         s21.b = new int;
1296         S2 s22 = move(s21);
1297         assert(s21 == s22);
1298     });
1299 
1300     // https://issues.dlang.org/show_bug.cgi?id=5661 test(1)
1301     static struct S3
1302     {
~thisS3::X1303         static struct X { int n = 0; ~this(){n = 0;} }
1304         X x;
1305     }
1306     static assert(hasElaborateDestructor!S3);
1307     S3 s31;
1308     s31.x.n = 1;
1309     S3 s32 = move(s31);
1310     assert(s31.x.n == 0);
1311     assert(s32.x.n == 1);
1312 
1313     // https://issues.dlang.org/show_bug.cgi?id=5661 test(2)
1314     static struct S4
1315     {
thisS4::X1316         static struct X { int n = 0; this(this){n = 0;} }
1317         X x;
1318     }
1319     static assert(hasElaborateCopyConstructor!S4);
1320     S4 s41;
1321     s41.x.n = 1;
1322     S4 s42 = move(s41);
1323     assert(s41.x.n == 0);
1324     assert(s42.x.n == 1);
1325 
1326     // https://issues.dlang.org/show_bug.cgi?id=13990 test
1327     class S5;
1328 
1329     S5 s51;
1330     S5 s52 = s51;
1331     S5 s53;
1332     s53 = move(s52);
1333     assert(s53 is s51);
1334 }
1335 
1336 @system unittest
1337 {
~thisS1338     static struct S { int n = 0; ~this() @system { n = 0; } }
1339     S a, b;
1340     static assert(!__traits(compiles, () @safe { move(a, b); }));
1341     static assert(!__traits(compiles, () @safe { move(a); }));
1342     a.n = 1;
1343     () @trusted { move(a, b); }();
1344     assert(a.n == 0);
1345     a.n = 1;
1346     () @trusted { move(a); }();
1347     assert(a.n == 0);
1348 }
1349 
1350 // https://issues.dlang.org/show_bug.cgi?id=6217
1351 @safe unittest
1352 {
1353     import std.algorithm.iteration : map;
1354     auto x = map!"a"([1,2,3]);
1355     x = move(x);
1356 }
1357 
1358 // https://issues.dlang.org/show_bug.cgi?id=8055
1359 @safe unittest
1360 {
1361     static struct S
1362     {
1363         int x;
~thisS1364         ~this()
1365         {
1366             assert(x == 0);
1367         }
1368     }
foo(S s)1369     S foo(S s)
1370     {
1371         return move(s);
1372     }
1373     S a;
1374     a.x = 0;
1375     auto b = foo(a);
1376     assert(b.x == 0);
1377 }
1378 
1379 // https://issues.dlang.org/show_bug.cgi?id=8057
1380 @system unittest
1381 {
1382     int n = 10;
1383     struct S
1384     {
1385         int x;
~thisS1386         ~this()
1387         {
1388             // Access to enclosing scope
1389             assert(n == 10);
1390         }
1391     }
foo(S s)1392     S foo(S s)
1393     {
1394         // Move nested struct
1395         return move(s);
1396     }
1397     S a;
1398     a.x = 1;
1399     auto b = foo(a);
1400     assert(b.x == 1);
1401 
1402     // Regression https://issues.dlang.org/show_bug.cgi?id=8171
Array(T)1403     static struct Array(T)
1404     {
1405         // nested struct has no member
1406         struct Payload
1407         {
1408             ~this() {}
1409         }
1410     }
1411     Array!int.Payload x = void;
1412     move(x);
1413     move(x, x);
1414 }
1415 
1416 private void moveEmplaceImpl(T)(ref scope T target, ref return scope T source)
1417 {
1418     import core.stdc.string : memcpy, memset;
1419     import std.traits : hasAliasing, hasElaborateAssign,
1420                         hasElaborateCopyConstructor, hasElaborateDestructor,
1421                         hasElaborateMove,
1422                         isAssignable, isStaticArray;
1423 
1424     static if (!is(T == class) && hasAliasing!T) if (!__ctfe)
1425     {
1426         import std.exception : doesPointTo;
1427         assert(!(doesPointTo(source, source) && !hasElaborateMove!T),
1428             "Cannot move object of type " ~ T.stringof ~ " with internal pointer unless `opPostMove` is defined.");
1429     }
1430 
1431     static if (is(T == struct))
1432     {
1433         //  Unsafe when compiling without -dip1000
1434         assert((() @trusted => &source !is &target)(), "source and target must not be identical");
1435 
1436         static if (hasElaborateAssign!T || !isAssignable!T)
1437             () @trusted { memcpy(&target, &source, T.sizeof); }();
1438         else
1439             target = source;
1440 
1441         static if (hasElaborateMove!T)
1442             __move_post_blt(target, source);
1443 
1444         // If the source defines a destructor or a postblit hook, we must obliterate the
1445         // object in order to avoid double freeing and undue aliasing
1446         static if (hasElaborateDestructor!T || hasElaborateCopyConstructor!T)
1447         {
1448             // If T is nested struct, keep original context pointer
1449             static if (__traits(isNested, T))
1450                 enum sz = T.sizeof - (void*).sizeof;
1451             else
1452                 enum sz = T.sizeof;
1453 
1454             static if (__traits(isZeroInit, T))
1455                 () @trusted { memset(&source, 0, sz); }();
1456             else
1457                 () @trusted { memcpy(&source, __traits(initSymbol, T).ptr, sz); }();
1458         }
1459     }
1460     else static if (isStaticArray!T)
1461     {
1462         for (size_t i = 0; i < source.length; ++i)
1463             move(source[i], target[i]);
1464     }
1465     else
1466     {
1467         // Primitive data (including pointers and arrays) or class -
1468         // assignment works great
1469         target = source;
1470     }
1471 }
1472 
1473 /**
1474  * Similar to $(LREF move) but assumes `target` is uninitialized. This
1475  * is more efficient because `source` can be blitted over `target`
1476  * without destroying or initializing it first.
1477  *
1478  * Params:
1479  *   source = value to be moved into target
1480  *   target = uninitialized value to be filled by source
1481  */
1482 void moveEmplace(T)(ref T source, ref T target) pure @system
1483 {
1484     moveEmplaceImpl(target, source);
1485 }
1486 
1487 ///
1488 pure nothrow @nogc @system unittest
1489 {
1490     static struct Foo
1491     {
1492     pure nothrow @nogc:
1493         this(int* ptr) { _ptr = ptr; }
1494         ~this() { if (_ptr) ++*_ptr; }
1495         int* _ptr;
1496     }
1497 
1498     int val;
1499     Foo foo1 = void; // uninitialized
1500     auto foo2 = Foo(&val); // initialized
1501     assert(foo2._ptr is &val);
1502 
1503     // Using `move(foo2, foo1)` would have an undefined effect because it would destroy
1504     // the uninitialized foo1.
1505     // moveEmplace directly overwrites foo1 without destroying or initializing it first.
1506     moveEmplace(foo2, foo1);
1507     assert(foo1._ptr is &val);
1508     assert(foo2._ptr is null);
1509     assert(val == 0);
1510 }
1511 
1512 // https://issues.dlang.org/show_bug.cgi?id=18913
1513 @safe unittest
1514 {
1515     static struct NoCopy
1516     {
1517         int payload;
1518         ~this() { }
1519         @disable this(this);
1520     }
1521 
1522     static void f(NoCopy[2]) { }
1523 
1524     NoCopy[2] ncarray = [ NoCopy(1), NoCopy(2) ];
1525 
1526     static assert(!__traits(compiles, f(ncarray)));
1527     f(move(ncarray));
1528 }
1529 
1530 // moveAll
1531 /**
1532 Calls `move(a, b)` for each element `a` in `src` and the corresponding
1533 element `b` in `tgt`, in increasing order.
1534 
1535 Preconditions:
1536 `walkLength(src) <= walkLength(tgt)`.
1537 This precondition will be asserted. If you cannot ensure there is enough room in
1538 `tgt` to accommodate all of `src` use $(LREF moveSome) instead.
1539 
1540 Params:
1541     src = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1542         movable elements.
1543     tgt = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1544         elements that elements from `src` can be moved into.
1545 
1546 Returns: The leftover portion of `tgt` after all elements from `src` have
1547 been moved.
1548  */
1549 InputRange2 moveAll(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
1550 if (isInputRange!InputRange1 && isInputRange!InputRange2
1551         && is(typeof(move(src.front, tgt.front))))
1552 {
1553     return moveAllImpl!move(src, tgt);
1554 }
1555 
1556 ///
1557 pure nothrow @safe @nogc unittest
1558 {
1559     int[3] a = [ 1, 2, 3 ];
1560     int[5] b;
1561     assert(moveAll(a[], b[]) is b[3 .. $]);
1562     assert(a[] == b[0 .. 3]);
1563     int[3] cmp = [ 1, 2, 3 ];
1564     assert(a[] == cmp[]);
1565 }
1566 
1567 /**
1568  * Similar to $(LREF moveAll) but assumes all elements in `tgt` are
1569  * uninitialized. Uses $(LREF moveEmplace) to move elements from
1570  * `src` over elements from `tgt`.
1571  */
1572 InputRange2 moveEmplaceAll(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt) @system
1573 if (isInputRange!InputRange1 && isInputRange!InputRange2
1574         && is(typeof(moveEmplace(src.front, tgt.front))))
1575 {
1576     return moveAllImpl!moveEmplace(src, tgt);
1577 }
1578 
1579 ///
1580 pure nothrow @nogc @system unittest
1581 {
1582     static struct Foo
1583     {
1584         ~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
1585         int* _ptr;
1586     }
1587     int[3] refs = [0, 1, 2];
1588     Foo[3] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2])];
1589     Foo[5] dst = void;
1590 
1591     auto tail = moveEmplaceAll(src[], dst[]); // move 3 value from src over dst
1592     assert(tail.length == 2); // returns remaining uninitialized values
1593     initializeAll(tail);
1594 
1595     import std.algorithm.searching : all;
1596     assert(src[].all!(e => e._ptr is null));
1597     assert(dst[0 .. 3].all!(e => e._ptr !is null));
1598 }
1599 
1600 @system unittest
1601 {
1602     struct InputRange
1603     {
1604         ref int front() { return data[0]; }
1605         void popFront() { data.popFront; }
1606         bool empty() { return data.empty; }
1607         int[] data;
1608     }
1609     auto a = InputRange([ 1, 2, 3 ]);
1610     auto b = InputRange(new int[5]);
1611     moveAll(a, b);
1612     assert(a.data == b.data[0 .. 3]);
1613     assert(a.data == [ 1, 2, 3 ]);
1614 }
1615 
1616 private InputRange2 moveAllImpl(alias moveOp, InputRange1, InputRange2)(
1617     ref InputRange1 src, ref InputRange2 tgt)
1618 {
1619     import std.exception : enforce;
1620 
1621     static if (isRandomAccessRange!InputRange1 && hasLength!InputRange1 && hasLength!InputRange2
1622          && hasSlicing!InputRange2 && isRandomAccessRange!InputRange2)
1623     {
1624         auto toMove = src.length;
1625         assert(toMove <= tgt.length, "Source buffer needs to be smaller or equal to the target buffer.");
1626         foreach (idx; 0 .. toMove)
1627             moveOp(src[idx], tgt[idx]);
1628         return tgt[toMove .. tgt.length];
1629     }
1630     else
1631     {
1632         for (; !src.empty; src.popFront(), tgt.popFront())
1633         {
1634             assert(!tgt.empty, "Source buffer needs to be smaller or equal to the target buffer.");
1635             moveOp(src.front, tgt.front);
1636         }
1637         return tgt;
1638     }
1639 }
1640 
1641 // moveSome
1642 /**
1643 Calls `move(a, b)` for each element `a` in `src` and the corresponding
1644 element `b` in `tgt`, in increasing order, stopping when either range has been
1645 exhausted.
1646 
1647 Params:
1648     src = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1649         movable elements.
1650     tgt = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with
1651         elements that elements from `src` can be moved into.
1652 
1653 Returns: The leftover portions of the two ranges after one or the other of the
1654 ranges have been exhausted.
1655  */
1656 Tuple!(InputRange1, InputRange2) moveSome(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt)
1657 if (isInputRange!InputRange1 && isInputRange!InputRange2
1658         && is(typeof(move(src.front, tgt.front))))
1659 {
1660     return moveSomeImpl!move(src, tgt);
1661 }
1662 
1663 ///
1664 pure nothrow @safe @nogc unittest
1665 {
1666     int[5] a = [ 1, 2, 3, 4, 5 ];
1667     int[3] b;
1668     assert(moveSome(a[], b[])[0] is a[3 .. $]);
1669     assert(a[0 .. 3] == b);
1670     assert(a == [ 1, 2, 3, 4, 5 ]);
1671 }
1672 
1673 /**
1674  * Same as $(LREF moveSome) but assumes all elements in `tgt` are
1675  * uninitialized. Uses $(LREF moveEmplace) to move elements from
1676  * `src` over elements from `tgt`.
1677  */
1678 Tuple!(InputRange1, InputRange2) moveEmplaceSome(InputRange1, InputRange2)(InputRange1 src, InputRange2 tgt) @system
1679 if (isInputRange!InputRange1 && isInputRange!InputRange2
1680         && is(typeof(move(src.front, tgt.front))))
1681 {
1682     return moveSomeImpl!moveEmplace(src, tgt);
1683 }
1684 
1685 ///
1686 pure nothrow @nogc @system unittest
1687 {
1688     static struct Foo
1689     {
1690         ~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
1691         int* _ptr;
1692     }
1693     int[4] refs = [0, 1, 2, 3];
1694     Foo[4] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2]), Foo(&refs[3])];
1695     Foo[3] dst = void;
1696 
1697     auto res = moveEmplaceSome(src[], dst[]);
1698     assert(res.length == 2);
1699 
1700     import std.algorithm.searching : all;
1701     assert(src[0 .. 3].all!(e => e._ptr is null));
1702     assert(src[3]._ptr !is null);
1703     assert(dst[].all!(e => e._ptr !is null));
1704 }
1705 
1706 private Tuple!(InputRange1, InputRange2) moveSomeImpl(alias moveOp, InputRange1, InputRange2)(
1707     ref InputRange1 src, ref InputRange2 tgt)
1708 {
1709     for (; !src.empty && !tgt.empty; src.popFront(), tgt.popFront())
1710         moveOp(src.front, tgt.front);
1711     return tuple(src, tgt);
1712  }
1713 
1714 
1715 // SwapStrategy
1716 /**
1717 Defines the swapping strategy for algorithms that need to swap
1718 elements in a range (such as partition and sort). The strategy
1719 concerns the swapping of elements that are not the core concern of the
1720 algorithm. For example, consider an algorithm that sorts $(D [ "abc",
1721 "b", "aBc" ]) according to `toUpper(a) < toUpper(b)`. That
1722 algorithm might choose to swap the two equivalent strings `"abc"`
1723 and `"aBc"`. That does not affect the sorting since both
1724 `["abc", "aBc", "b" ]` and `[ "aBc", "abc", "b" ]` are valid
1725 outcomes.
1726 
1727 Some situations require that the algorithm must NOT ever change the
1728 relative ordering of equivalent elements (in the example above, only
1729 `[ "abc", "aBc", "b" ]` would be the correct result). Such
1730 algorithms are called $(B stable). If the ordering algorithm may swap
1731 equivalent elements discretionarily, the ordering is called $(B
1732 unstable).
1733 
1734 Yet another class of algorithms may choose an intermediate tradeoff by
1735 being stable only on a well-defined subrange of the range. There is no
1736 established terminology for such behavior; this library calls it $(B
1737 semistable).
1738 
1739 Generally, the `stable` ordering strategy may be more costly in
1740 time and/or space than the other two because it imposes additional
1741 constraints. Similarly, `semistable` may be costlier than $(D
1742 unstable). As (semi-)stability is not needed very often, the ordering
1743 algorithms in this module parameterized by `SwapStrategy` all
1744 choose `SwapStrategy.unstable` as the default.
1745 */
1746 
1747 enum SwapStrategy
1748 {
1749     /**
1750        Allows freely swapping of elements as long as the output
1751        satisfies the algorithm's requirements.
1752     */
1753     unstable,
1754     /**
1755        In algorithms partitioning ranges in two, preserve relative
1756        ordering of elements only to the left of the partition point.
1757     */
1758     semistable,
1759     /**
1760        Preserve the relative ordering of elements to the largest
1761        extent allowed by the algorithm's requirements.
1762     */
1763     stable,
1764 }
1765 
1766 ///
1767 @safe unittest
1768 {
1769     int[] a = [0, 1, 2, 3];
1770     assert(remove!(SwapStrategy.stable)(a, 1) == [0, 2, 3]);
1771     a = [0, 1, 2, 3];
1772     assert(remove!(SwapStrategy.unstable)(a, 1) == [0, 3, 2]);
1773 }
1774 
1775 ///
1776 @safe unittest
1777 {
1778     import std.algorithm.sorting : partition;
1779 
1780     // Put stuff greater than 3 on the left
1781     auto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1782     assert(partition!(a => a > 3, SwapStrategy.stable)(arr) == [1, 2, 3]);
1783     assert(arr == [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]);
1784 
1785     arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1786     assert(partition!(a => a > 3, SwapStrategy.semistable)(arr) == [2, 3, 1]);
1787     assert(arr == [4, 5, 6, 7, 8, 9, 10, 2, 3, 1]);
1788 
1789     arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1790     assert(partition!(a => a > 3, SwapStrategy.unstable)(arr) == [3, 2, 1]);
1791     assert(arr == [10, 9, 8, 4, 5, 6, 7, 3, 2, 1]);
1792 }
1793 
1794 private template isValidIntegralTuple(T)
1795 {
1796     import std.traits : isIntegral;
1797     import std.typecons : isTuple;
1798     static if (isTuple!T)
1799     {
1800         enum isValidIntegralTuple = T.length == 2 &&
1801                 isIntegral!(typeof(T.init[0])) && isIntegral!(typeof(T.init[0]));
1802     }
1803     else
1804     {
1805         enum isValidIntegralTuple = isIntegral!T;
1806     }
1807 }
1808 
1809 
1810 /**
1811 Eliminates elements at given offsets from `range` and returns the shortened
1812 range.
1813 
1814 For example, here is how to remove a single element from an array:
1815 
1816 ----
1817 string[] a = [ "a", "b", "c", "d" ];
1818 a = a.remove(1); // remove element at offset 1
1819 assert(a == [ "a", "c", "d"]);
1820 ----
1821 
1822 Note that `remove` does not change the length of the original range directly;
1823 instead, it returns the shortened range. If its return value is not assigned to
1824 the original range, the original range will retain its original length, though
1825 its contents will have changed:
1826 
1827 ----
1828 int[] a = [ 3, 5, 7, 8 ];
1829 assert(remove(a, 1) == [ 3, 7, 8 ]);
1830 assert(a == [ 3, 7, 8, 8 ]);
1831 ----
1832 
1833 The element at offset `1` has been removed and the rest of the elements have
1834 shifted up to fill its place, however, the original array remains of the same
1835 length. This is because all functions in `std.algorithm` only change $(I
1836 content), not $(I topology). The value `8` is repeated because $(LREF move) was
1837 invoked to rearrange elements, and on integers `move` simply copies the source
1838 to the destination.  To replace `a` with the effect of the removal, simply
1839 assign the slice returned by `remove` to it, as shown in the first example.
1840 
1841 Multiple indices can be passed into `remove`. In that case,
1842 elements at the respective indices are all removed. The indices must
1843 be passed in increasing order, otherwise an exception occurs.
1844 
1845 ----
1846 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
1847 assert(remove(a, 1, 3, 5) ==
1848     [ 0, 2, 4, 6, 7, 8, 9, 10 ]);
1849 ----
1850 
1851 (Note that all indices refer to slots in the $(I original) array, not
1852 in the array as it is being progressively shortened.)
1853 
1854 Tuples of two integral offsets can be used to remove an indices range:
1855 
1856 ----
1857 int[] a = [ 3, 4, 5, 6, 7];
1858 assert(remove(a, 1, tuple(1, 3), 9) == [ 3, 6, 7 ]);
1859 ----
1860 
1861 The tuple passes in a range closed to the left and open to
1862 the right (consistent with built-in slices), e.g. `tuple(1, 3)`
1863 means indices `1` and `2` but not `3`.
1864 
1865 Finally, any combination of integral offsets and tuples composed of two integral
1866 offsets can be passed in:
1867 
1868 ----
1869 int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
1870 assert(remove(a, 1, tuple(3, 5), 9) == [ 0, 2, 5, 6, 7, 8, 10 ]);
1871 ----
1872 
1873 In this case, the slots at positions 1, 3, 4, and 9 are removed from
1874 the array.
1875 
1876 If the need is to remove some elements in the range but the order of
1877 the remaining elements does not have to be preserved, you may want to
1878 pass `SwapStrategy.unstable` to `remove`.
1879 
1880 ----
1881 int[] a = [ 0, 1, 2, 3 ];
1882 assert(remove!(SwapStrategy.unstable)(a, 1) == [ 0, 3, 2 ]);
1883 ----
1884 
1885 In the case above, the element at slot `1` is removed, but replaced
1886 with the last element of the range. Taking advantage of the relaxation
1887 of the stability requirement, `remove` moved elements from the end
1888 of the array over the slots to be removed. This way there is less data
1889 movement to be done which improves the execution time of the function.
1890 
1891 The function `remove` works on bidirectional ranges that have assignable
1892 lvalue elements. The moving strategy is (listed from fastest to slowest):
1893 
1894 $(UL
1895         $(LI If $(D s == SwapStrategy.unstable && isRandomAccessRange!Range &&
1896 hasLength!Range && hasLvalueElements!Range), then elements are moved from the
1897 end of the range into the slots to be filled. In this case, the absolute
1898 minimum of moves is performed.)
1899         $(LI Otherwise, if $(D s ==
1900 SwapStrategy.unstable && isBidirectionalRange!Range && hasLength!Range
1901 && hasLvalueElements!Range), then elements are still moved from the
1902 end of the range, but time is spent on advancing between slots by repeated
1903 calls to `range.popFront`.)
1904         $(LI Otherwise, elements are moved
1905 incrementally towards the front of `range`; a given element is never
1906 moved several times, but more elements are moved than in the previous
1907 cases.)
1908 )
1909 
1910 Params:
1911     s = a SwapStrategy to determine if the original order needs to be preserved
1912     range = a $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives)
1913     with a length member
1914     offset = which element(s) to remove
1915 
1916 Returns:
1917     A range containing all of the elements of range with offset removed.
1918 */
1919 Range remove
1920 (SwapStrategy s = SwapStrategy.stable, Range, Offset ...)
1921 (Range range, Offset offset)
1922 if (Offset.length >= 1 && allSatisfy!(isValidIntegralTuple, Offset))
1923 {
1924     // Activate this check when the deprecation of non-integral tuples is over
1925     //import std.traits : isIntegral;
1926     //import std.typecons : isTuple;
1927     //static foreach (T; Offset)
1928     //{
1929         //static if (isTuple!T)
1930         //{
1931             //static assert(T.length == 2 &&
1932                     //isIntegral!(typeof(T.init[0])) && isIntegral!(typeof(T.init[0])),
1933                 //"Each offset must be an integral or a tuple of two integrals." ~
1934                 //"Use `arr.remove(pos1, pos2)` or `arr.remove(tuple(start, begin))`");
1935         //}
1936         //else
1937         //{
1938             //static assert(isIntegral!T,
1939                 //"Each offset must be an integral or a tuple of two integrals." ~
1940                 //"Use `arr.remove(pos1, pos2)` or `arr.remove(tuple(start, begin))`");
1941         //}
1942     //}
1943     return removeImpl!s(range, offset);
1944 }
1945 
1946 deprecated("Use of non-integral tuples is deprecated. Use remove(tuple(start, end).")
1947 Range remove
1948 (SwapStrategy s = SwapStrategy.stable, Range, Offset ...)
1949 (Range range, Offset offset)
1950 if (Offset.length >= 1 && !allSatisfy!(isValidIntegralTuple, Offset))
1951 {
1952     return removeImpl!s(range, offset);
1953 }
1954 
1955 ///
1956 @safe pure unittest
1957 {
1958     import std.typecons : tuple;
1959 
1960     auto a = [ 0, 1, 2, 3, 4, 5 ];
1961     assert(remove!(SwapStrategy.stable)(a, 1) == [ 0, 2, 3, 4, 5 ]);
1962     a = [ 0, 1, 2, 3, 4, 5 ];
1963     assert(remove!(SwapStrategy.stable)(a, 1, 3) == [ 0, 2, 4, 5] );
1964     a = [ 0, 1, 2, 3, 4, 5 ];
1965     assert(remove!(SwapStrategy.stable)(a, 1, tuple(3, 6)) == [ 0, 2 ]);
1966 
1967     a = [ 0, 1, 2, 3, 4, 5 ];
1968     assert(remove!(SwapStrategy.unstable)(a, 1) == [0, 5, 2, 3, 4]);
1969     a = [ 0, 1, 2, 3, 4, 5 ];
1970     assert(remove!(SwapStrategy.unstable)(a, tuple(1, 4)) == [0, 5, 4]);
1971 }
1972 
1973 ///
1974 @safe pure unittest
1975 {
1976     import std.typecons : tuple;
1977 
1978     // Delete an index
1979     assert([4, 5, 6].remove(1) == [4, 6]);
1980 
1981     // Delete multiple indices
1982     assert([4, 5, 6, 7, 8].remove(1, 3) == [4, 6, 8]);
1983 
1984     // Use an indices range
1985     assert([4, 5, 6, 7, 8].remove(tuple(1, 3)) == [4, 7, 8]);
1986 
1987     // Use an indices range and individual indices
1988     assert([4, 5, 6, 7, 8].remove(0, tuple(1, 3), 4) == [7]);
1989 }
1990 
1991 /// `SwapStrategy.unstable` is faster, but doesn't guarantee the same order of the original array
1992 @safe pure unittest
1993 {
1994     assert([5, 6, 7, 8].remove!(SwapStrategy.stable)(1) == [5, 7, 8]);
1995     assert([5, 6, 7, 8].remove!(SwapStrategy.unstable)(1) == [5, 8, 7]);
1996 }
1997 
1998 private auto removeImpl(SwapStrategy s, Range, Offset...)(Range range, Offset offset)
1999 {
2000     static if (isNarrowString!Range)
2001     {
2002         static assert(isMutable!(typeof(range[0])),
2003                 "Elements must be mutable to remove");
2004         static assert(s == SwapStrategy.stable,
2005                 "Only stable removing can be done for character arrays");
2006         return removeStableString(range, offset);
2007     }
2008     else
2009     {
2010         static assert(isBidirectionalRange!Range,
2011                 "Range must be bidirectional");
2012         static assert(hasLvalueElements!Range,
2013                 "Range must have Lvalue elements (see std.range.hasLvalueElements)");
2014 
2015         static if (s == SwapStrategy.unstable)
2016         {
2017             static assert(hasLength!Range,
2018                     "Range must have `length` for unstable remove");
2019             return removeUnstable(range, offset);
2020         }
2021         else static if (s == SwapStrategy.stable)
2022             return removeStable(range, offset);
2023         else
2024             static assert(false,
2025                     "Only SwapStrategy.stable and SwapStrategy.unstable are supported");
2026     }
2027 }
2028 
2029 @safe unittest
2030 {
2031     import std.exception : assertThrown;
2032     import std.range;
2033 
2034     // https://issues.dlang.org/show_bug.cgi?id=10173
2035     int[] test = iota(0, 10).array();
2036     assertThrown(remove!(SwapStrategy.stable)(test, tuple(2, 4), tuple(1, 3)));
2037     assertThrown(remove!(SwapStrategy.unstable)(test, tuple(2, 4), tuple(1, 3)));
2038     assertThrown(remove!(SwapStrategy.stable)(test, 2, 4, 1, 3));
2039     assertThrown(remove!(SwapStrategy.unstable)(test, 2, 4, 1, 3));
2040 }
2041 
2042 @safe unittest
2043 {
2044     import std.range;
2045     int[] a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2046     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2047     assert(remove!(SwapStrategy.stable)(a, 1) ==
2048         [ 0, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]);
2049 
2050     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2051     assert(remove!(SwapStrategy.unstable)(a, 0, 10) ==
2052            [ 9, 1, 2, 3, 4, 5, 6, 7, 8 ]);
2053 
2054     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2055     assert(remove!(SwapStrategy.unstable)(a, 0, tuple(9, 11)) ==
2056             [ 8, 1, 2, 3, 4, 5, 6, 7 ]);
2057     // https://issues.dlang.org/show_bug.cgi?id=5224
2058     a = [ 1, 2, 3, 4 ];
2059     assert(remove!(SwapStrategy.unstable)(a, 2) ==
2060            [ 1, 2, 4 ]);
2061 
2062     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2063     assert(remove!(SwapStrategy.stable)(a, 1, 5) ==
2064         [ 0, 2, 3, 4, 6, 7, 8, 9, 10 ]);
2065 
2066     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2067     assert(remove!(SwapStrategy.stable)(a, 1, 3, 5)
2068             == [ 0, 2, 4, 6, 7, 8, 9, 10]);
2069     a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
2070     assert(remove!(SwapStrategy.stable)(a, 1, tuple(3, 5))
2071             == [ 0, 2, 5, 6, 7, 8, 9, 10]);
2072 
2073     a = iota(0, 10).array();
2074     assert(remove!(SwapStrategy.unstable)(a, tuple(1, 4), tuple(6, 7))
2075             == [0, 9, 8, 7, 4, 5]);
2076 }
2077 
2078 // https://issues.dlang.org/show_bug.cgi?id=11576
2079 @safe unittest
2080 {
2081     auto arr = [1,2,3];
2082     arr = arr.remove!(SwapStrategy.unstable)(2);
2083     assert(arr == [1,2]);
2084 
2085 }
2086 
2087 // https://issues.dlang.org/show_bug.cgi?id=12889
2088 @safe unittest
2089 {
2090     import std.range;
2091     int[1][] arr = [[0], [1], [2], [3], [4], [5], [6]];
2092     auto orig = arr.dup;
2093     foreach (i; iota(arr.length))
2094     {
2095         assert(orig == arr.remove!(SwapStrategy.unstable)(tuple(i,i)));
2096         assert(orig == arr.remove!(SwapStrategy.stable)(tuple(i,i)));
2097     }
2098 }
2099 
2100 @safe unittest
2101 {
2102     char[] chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
2103     remove(chars, 4);
2104     assert(chars == ['a', 'b', 'c', 'd', 'f', 'g', 'h', 'h']);
2105 
2106     char[] bigChars = "∑œ∆¬é˚˙ƒé∂ß¡¡".dup;
2107     assert(remove(bigChars, tuple(4, 6), 8) == ("∑œ∆¬˙ƒ∂ß¡¡"));
2108 
2109     import std.exception : assertThrown;
2110     assertThrown(remove(bigChars.dup, 1, 0));
2111     assertThrown(remove(bigChars.dup, tuple(4, 3)));
2112 }
2113 
2114 private Range removeUnstable(Range, Offset...)(Range range, Offset offset)
2115 {
2116     Tuple!(size_t, "pos", size_t, "len")[offset.length] blackouts;
2117     foreach (i, v; offset)
2118     {
2119         static if (is(typeof(v[0]) : size_t) && is(typeof(v[1]) : size_t))
2120         {
2121             blackouts[i].pos = v[0];
2122             blackouts[i].len = v[1] - v[0];
2123         }
2124         else
2125         {
2126             static assert(is(typeof(v) : size_t), typeof(v).stringof);
2127             blackouts[i].pos = v;
2128             blackouts[i].len = 1;
2129         }
2130         static if (i > 0)
2131         {
2132             import std.exception : enforce;
2133 
2134             enforce(blackouts[i - 1].pos + blackouts[i - 1].len
2135                     <= blackouts[i].pos,
2136                 "remove(): incorrect ordering of elements to remove");
2137         }
2138     }
2139 
2140     size_t left = 0, right = offset.length - 1;
2141     auto tgt = range.save;
2142     size_t tgtPos = 0;
2143 
2144     while (left <= right)
2145     {
2146         // Look for a blackout on the right
2147         if (blackouts[right].pos + blackouts[right].len >= range.length)
2148         {
2149             range.popBackExactly(blackouts[right].len);
2150 
2151             // Since right is unsigned, we must check for this case, otherwise
2152             // we might turn it into size_t.max and the loop condition will not
2153             // fail when it should.
2154             if (right > 0)
2155             {
2156                 --right;
2157                 continue;
2158             }
2159             else
2160                 break;
2161         }
2162         // Advance to next blackout on the left
2163         assert(blackouts[left].pos >= tgtPos, "Next blackout on the left shouldn't appear before the target.");
2164         tgt.popFrontExactly(blackouts[left].pos - tgtPos);
2165         tgtPos = blackouts[left].pos;
2166 
2167         // Number of elements to the right of blackouts[right]
2168         immutable tailLen = range.length - (blackouts[right].pos + blackouts[right].len);
2169         size_t toMove = void;
2170         if (tailLen < blackouts[left].len)
2171         {
2172             toMove = tailLen;
2173             blackouts[left].pos += toMove;
2174             blackouts[left].len -= toMove;
2175         }
2176         else
2177         {
2178             toMove = blackouts[left].len;
2179             ++left;
2180         }
2181         tgtPos += toMove;
2182         foreach (i; 0 .. toMove)
2183         {
2184             move(range.back, tgt.front);
2185             range.popBack();
2186             tgt.popFront();
2187         }
2188     }
2189 
2190     return range;
2191 }
2192 
2193 private Range removeStable(Range, Offset...)(Range range, Offset offset)
2194 {
2195     auto result = range;
2196     auto src = range, tgt = range;
2197     size_t pos;
2198     foreach (pass, i; offset)
2199     {
2200         static if (is(typeof(i[0])) && is(typeof(i[1])))
2201         {
2202             auto from = i[0], delta = i[1] - i[0];
2203         }
2204         else
2205         {
2206             auto from = i;
2207             enum delta = 1;
2208         }
2209 
2210         static if (pass > 0)
2211         {
2212             import std.exception : enforce;
2213             enforce(pos <= from,
2214                     "remove(): incorrect ordering of elements to remove");
2215 
2216             for (; pos < from; ++pos, src.popFront(), tgt.popFront())
2217             {
2218                 move(src.front, tgt.front);
2219             }
2220         }
2221         else
2222         {
2223             src.popFrontExactly(from);
2224             tgt.popFrontExactly(from);
2225             pos = from;
2226         }
2227         // now skip source to the "to" position
2228         src.popFrontExactly(delta);
2229         result.popBackExactly(delta);
2230         pos += delta;
2231     }
2232     // leftover move
2233     moveAll(src, tgt);
2234     return result;
2235 }
2236 
2237 private Range removeStableString(Range, Offset...)(Range range, Offset offsets)
2238 {
2239     import std.utf : stride;
2240     size_t charIdx = 0;
2241     size_t dcharIdx = 0;
2242     size_t charShift = 0;
2243 
2244     void skipOne()
2245     {
2246         charIdx += stride(range[charIdx .. $]);
2247         ++dcharIdx;
2248     }
2249 
2250     void copyBackOne()
2251     {
2252         auto encodedLen = stride(range[charIdx .. $]);
2253         foreach (j; charIdx .. charIdx + encodedLen)
2254             range[j - charShift] = range[j];
2255         charIdx += encodedLen;
2256         ++dcharIdx;
2257     }
2258 
2259     foreach (pass, i; offsets)
2260     {
2261         static if (is(typeof(i[0])) && is(typeof(i[1])))
2262         {
2263             auto from = i[0];
2264             auto delta = i[1] - i[0];
2265         }
2266         else
2267         {
2268             auto from = i;
2269             enum delta = 1;
2270         }
2271 
2272         import std.exception : enforce;
2273         enforce(dcharIdx <= from && delta >= 0,
2274                 "remove(): incorrect ordering of elements to remove");
2275 
2276         while (dcharIdx < from)
2277             static if (pass == 0)
2278                 skipOne();
2279             else
2280                 copyBackOne();
2281 
2282         auto mark = charIdx;
2283         while (dcharIdx < from + delta)
2284             skipOne();
2285         charShift += charIdx - mark;
2286     }
2287 
2288     foreach (i; charIdx .. range.length)
2289         range[i - charShift] = range[i];
2290 
2291     return range[0 .. $ - charShift];
2292 }
2293 
2294 // Use of dynamic arrays as offsets is too error-prone
2295 // https://issues.dlang.org/show_bug.cgi?id=12086
2296 // Activate these tests once the deprecation period of remove with non-integral tuples is over
2297 @safe unittest
2298 {
2299     //static assert(!__traits(compiles, [0, 1, 2, 3, 4].remove([1, 3]) == [0, 3, 4]));
2300     static assert(__traits(compiles, [0, 1, 2, 3, 4].remove(1, 3) == [0, 2, 4]));
2301     //static assert(!__traits(compiles, assert([0, 1, 2, 3, 4].remove([1, 3, 4]) == [0, 3, 4])));
2302     //static assert(!__traits(compiles, assert([0, 1, 2, 3, 4].remove(tuple(1, 3, 4)) == [0, 3, 4])));
2303 
2304     import std.range : only;
2305     //static assert(!__traits(compiles, assert([0, 1, 2, 3, 4].remove(only(1, 3)) == [0, 3, 4])));
2306     static assert(__traits(compiles, assert([0, 1, 2, 3, 4].remove(1, 3) == [0, 2, 4])));
2307 }
2308 
2309 /**
2310 Reduces the length of the
2311 $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives) `range` by removing
2312 elements that satisfy `pred`. If `s = SwapStrategy.unstable`,
2313 elements are moved from the right end of the range over the elements
2314 to eliminate. If `s = SwapStrategy.stable` (the default),
2315 elements are moved progressively to front such that their relative
2316 order is preserved. Returns the filtered range.
2317 
2318 Params:
2319     range = a bidirectional ranges with lvalue elements
2320         or mutable character arrays
2321 
2322 Returns:
2323     the range with all of the elements where `pred` is `true`
2324     removed
2325 */
2326 Range remove(alias pred, SwapStrategy s = SwapStrategy.stable, Range)(Range range)
2327 {
2328     import std.functional : unaryFun;
2329     alias pred_ = unaryFun!pred;
2330     static if (isNarrowString!Range)
2331     {
2332         static assert(isMutable!(typeof(range[0])),
2333                 "Elements must be mutable to remove");
2334         static assert(s == SwapStrategy.stable,
2335                 "Only stable removing can be done for character arrays");
2336         return removePredString!pred_(range);
2337     }
2338     else
2339     {
2340         static assert(isBidirectionalRange!Range,
2341                 "Range must be bidirectional");
2342         static assert(hasLvalueElements!Range,
2343                 "Range must have Lvalue elements (see std.range.hasLvalueElements)");
2344         static if (s == SwapStrategy.unstable)
2345             return removePredUnstable!pred_(range);
2346         else static if (s == SwapStrategy.stable)
2347             return removePredStable!pred_(range);
2348         else
2349             static assert(false,
2350                     "Only SwapStrategy.stable and SwapStrategy.unstable are supported");
2351     }
2352 }
2353 
2354 ///
2355 @safe unittest
2356 {
2357     static immutable base = [1, 2, 3, 2, 4, 2, 5, 2];
2358 
2359     int[] arr = base[].dup;
2360 
2361     // using a string-based predicate
2362     assert(remove!("a == 2")(arr) == [ 1, 3, 4, 5 ]);
2363 
2364     // The original array contents have been modified,
2365     // so we need to reset it to its original state.
2366     // The length is unmodified however.
2367     arr[] = base[];
2368 
2369     // using a lambda predicate
2370     assert(remove!(a => a == 2)(arr) == [ 1, 3, 4, 5 ]);
2371 }
2372 
2373 @safe unittest
2374 {
2375     int[] a = [ 1, 2, 3, 2, 3, 4, 5, 2, 5, 6 ];
2376     assert(remove!("a == 2", SwapStrategy.unstable)(a) ==
2377             [ 1, 6, 3, 5, 3, 4, 5 ]);
2378     a = [ 1, 2, 3, 2, 3, 4, 5, 2, 5, 6 ];
2379     assert(remove!("a == 2", SwapStrategy.stable)(a) ==
2380             [ 1, 3, 3, 4, 5, 5, 6 ]);
2381 }
2382 
2383 @nogc @safe unittest
2384 {
2385     // @nogc test
2386     static int[] arr = [0,1,2,3,4,5,6,7,8,9];
2387     alias pred = e => e < 5;
2388 
2389     auto r = arr[].remove!(SwapStrategy.unstable)(0);
2390     r = r.remove!(SwapStrategy.stable)(0);
2391     r = r.remove!(pred, SwapStrategy.unstable);
2392     r = r.remove!(pred, SwapStrategy.stable);
2393 }
2394 
2395 @safe unittest
2396 {
2397     import std.algorithm.comparison : min;
2398     import std.algorithm.searching : all, any;
2399     import std.algorithm.sorting : isStrictlyMonotonic;
2400     import std.array : array;
2401     import std.meta : AliasSeq;
2402     import std.range : iota, only;
2403     import std.typecons : Tuple;
2404     alias E = Tuple!(int, int);
2405     alias S = Tuple!(E);
2406     S[] soffsets;
2407     foreach (start; 0 .. 5)
2408     foreach (end; min(start+1,5) .. 5)
2409           soffsets ~= S(E(start,end));
2410     alias D = Tuple!(E, E);
2411     D[] doffsets;
2412     foreach (start1; 0 .. 10)
2413     foreach (end1; min(start1+1,10) .. 10)
2414     foreach (start2; end1 .. 10)
2415     foreach (end2; min(start2+1,10) .. 10)
2416           doffsets ~= D(E(start1,end1),E(start2,end2));
2417     alias T = Tuple!(E, E, E);
2418     T[] toffsets;
2419     foreach (start1; 0 .. 15)
2420     foreach (end1; min(start1+1,15) .. 15)
2421     foreach (start2; end1 .. 15)
2422     foreach (end2; min(start2+1,15) .. 15)
2423     foreach (start3; end2 .. 15)
2424     foreach (end3; min(start3+1,15) .. 15)
2425             toffsets ~= T(E(start1,end1),E(start2,end2),E(start3,end3));
2426 
2427     static void verify(O...)(int[] r, int len, int removed, bool stable, O offsets)
2428     {
2429         assert(r.length == len - removed);
2430         assert(!stable || r.isStrictlyMonotonic);
2431         assert(r.all!(e => all!(o => e < o[0] || e >= o[1])(offsets.only)));
2432     }
2433 
2434     static foreach (offsets; AliasSeq!(soffsets,doffsets,toffsets))
2435     foreach (os; offsets)
2436     {
2437         int len = 5*os.length;
2438         auto w = iota(0, len).array;
2439         auto x = w.dup;
2440         auto y = w.dup;
2441         auto z = w.dup;
2442         alias pred = e => any!(o => o[0] <= e && e < o[1])(only(os.expand));
2443         w = w.remove!(SwapStrategy.unstable)(os.expand);
2444         x = x.remove!(SwapStrategy.stable)(os.expand);
2445         y = y.remove!(pred, SwapStrategy.unstable);
2446         z = z.remove!(pred, SwapStrategy.stable);
2447         int removed;
2448         foreach (o; os)
2449             removed += o[1] - o[0];
2450         verify(w, len, removed, false, os[]);
2451         verify(x, len, removed, true, os[]);
2452         verify(y, len, removed, false, os[]);
2453         verify(z, len, removed, true, os[]);
2454         assert(w == y);
2455         assert(x == z);
2456     }
2457 }
2458 
2459 @safe unittest
2460 {
2461     char[] chars = "abcdefg".dup;
2462     assert(chars.remove!(dc => dc == 'c' || dc == 'f') == "abdeg");
2463     assert(chars == "abdegfg");
2464 
2465     assert(chars.remove!"a == 'd'" == "abegfg");
2466 
2467     char[] bigChars = "¥^¨^©é√∆π".dup;
2468     assert(bigChars.remove!(dc => dc == "¨"d[0] || dc == "é"d[0]) ==  "¥^^©√∆π");
2469 }
2470 
2471 private Range removePredUnstable(alias pred, Range)(Range range)
2472 {
2473     auto result = range;
2474     for (;!range.empty;)
2475     {
2476         if (!pred(range.front))
2477         {
2478             range.popFront();
2479             continue;
2480         }
2481         move(range.back, range.front);
2482         range.popBack();
2483         result.popBack();
2484     }
2485     return result;
2486 }
2487 
2488 private Range removePredStable(alias pred, Range)(Range range)
2489 {
2490     auto result = range;
2491     auto tgt = range;
2492     for (; !range.empty; range.popFront())
2493     {
2494         if (pred(range.front))
2495         {
2496             // yank this guy
2497             result.popBack();
2498             continue;
2499         }
2500         // keep this guy
2501         move(range.front, tgt.front);
2502         tgt.popFront();
2503     }
2504     return result;
2505 }
2506 
2507 private Range removePredString(alias pred, SwapStrategy s = SwapStrategy.stable, Range)
2508 (Range range)
2509 {
2510     import std.utf : decode;
2511     import std.functional : unaryFun;
2512 
2513     alias pred_ = unaryFun!pred;
2514 
2515     size_t charIdx = 0;
2516     size_t charShift = 0;
2517     while (charIdx < range.length)
2518     {
2519         size_t start = charIdx;
2520         if (pred_(decode(range, charIdx)))
2521         {
2522             charShift += charIdx - start;
2523             break;
2524         }
2525     }
2526     while (charIdx < range.length)
2527     {
2528         size_t start = charIdx;
2529         auto doRemove = pred_(decode(range, charIdx));
2530         auto encodedLen = charIdx - start;
2531         if (doRemove)
2532             charShift += encodedLen;
2533         else
2534             foreach (i; start .. charIdx)
2535                 range[i - charShift] = range[i];
2536     }
2537 
2538     return range[0 .. $ - charShift];
2539 }
2540 
2541 // reverse
2542 /**
2543 Reverses `r` in-place.  Performs `r.length / 2` evaluations of `swap`.
2544 UTF sequences consisting of multiple code units are preserved properly.
2545 
2546 Params:
2547     r = a $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives)
2548         with either swappable elements, a random access range with a length member,
2549         or a narrow string
2550 
2551 Returns: `r`
2552 
2553 Note:
2554     When passing a string with unicode modifiers on characters, such as `\u0301`,
2555     this function will not properly keep the position of the modifier. For example,
2556     reversing `ba\u0301d` ("bád") will result in d\u0301ab ("d́ab") instead of
2557     `da\u0301b` ("dáb").
2558 
2559 See_Also: $(REF retro, std,range) for a lazy reverse without changing `r`
2560 */
2561 Range reverse(Range)(Range r)
2562 if (isBidirectionalRange!Range &&
2563         (hasSwappableElements!Range ||
2564          (hasAssignableElements!Range && hasLength!Range && isRandomAccessRange!Range) ||
2565          (isNarrowString!Range && isAssignable!(ElementType!Range))))
2566 {
2567     static if (isRandomAccessRange!Range && hasLength!Range)
2568     {
2569         //swapAt is in fact the only way to swap non lvalue ranges
2570         immutable last = r.length - 1;
2571         immutable steps = r.length / 2;
2572         for (size_t i = 0; i < steps; i++)
2573         {
2574             r.swapAt(i, last - i);
2575         }
2576         return r;
2577     }
2578     else static if (isNarrowString!Range && isAssignable!(ElementType!Range))
2579     {
2580         import std.string : representation;
2581         import std.utf : stride;
2582 
2583         auto raw = representation(r);
2584         for (size_t i = 0; i < r.length;)
2585         {
2586             immutable step = stride(r, i);
2587             if (step > 1)
2588             {
2589                 .reverse(raw[i .. i + step]);
2590                 i += step;
2591             }
2592             else
2593             {
2594                 ++i;
2595             }
2596         }
2597         reverse(raw);
2598         return r;
2599     }
2600     else
2601     {
2602         while (!r.empty)
2603         {
2604             swap(r.front, r.back);
2605             r.popFront();
2606             if (r.empty) break;
2607             r.popBack();
2608         }
2609         return r;
2610     }
2611 }
2612 
2613 ///
2614 @safe unittest
2615 {
2616     int[] arr = [ 1, 2, 3 ];
2617     assert(arr.reverse == [ 3, 2, 1 ]);
2618 }
2619 
2620 @safe unittest
2621 {
2622     int[] range = null;
2623     reverse(range);
2624     range = [ 1 ];
2625     reverse(range);
2626     assert(range == [1]);
2627     range = [1, 2];
2628     reverse(range);
2629     assert(range == [2, 1]);
2630     range = [1, 2, 3];
2631     assert(range.reverse == [3, 2, 1]);
2632 }
2633 
2634 ///
2635 @safe unittest
2636 {
2637     char[] arr = "hello\U00010143\u0100\U00010143".dup;
2638     assert(arr.reverse == "\U00010143\u0100\U00010143olleh");
2639 }
2640 
2641 @safe unittest
2642 {
2643     void test(string a, string b)
2644     {
2645         auto c = a.dup;
2646         reverse(c);
2647         assert(c == b, c ~ " != " ~ b);
2648     }
2649 
2650     test("a", "a");
2651     test(" ", " ");
2652     test("\u2029", "\u2029");
2653     test("\u0100", "\u0100");
2654     test("\u0430", "\u0430");
2655     test("\U00010143", "\U00010143");
2656     test("abcdefcdef", "fedcfedcba");
2657     test("hello\U00010143\u0100\U00010143", "\U00010143\u0100\U00010143olleh");
2658 }
2659 
2660 /**
2661     The strip group of functions allow stripping of either leading, trailing,
2662     or both leading and trailing elements.
2663 
2664     The `stripLeft` function will strip the `front` of the range,
2665     the `stripRight` function will strip the `back` of the range,
2666     while the `strip` function will strip both the `front` and `back`
2667     of the range.
2668 
2669     Note that the `strip` and `stripRight` functions require the range to
2670     be a $(LREF BidirectionalRange) range.
2671 
2672     All of these functions come in two varieties: one takes a target element,
2673     where the range will be stripped as long as this element can be found.
2674     The other takes a lambda predicate, where the range will be stripped as
2675     long as the predicate returns true.
2676 
2677     Params:
2678         range = a $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives)
2679         or $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
2680         element = the elements to remove
2681 
2682     Returns:
2683         a Range with all of range except element at the start and end
2684 */
2685 Range strip(Range, E)(Range range, E element)
2686 if (isBidirectionalRange!Range && is(typeof(range.front == element) : bool))
2687 {
2688     return range.stripLeft(element).stripRight(element);
2689 }
2690 
2691 /// ditto
2692 Range strip(alias pred, Range)(Range range)
2693 if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool))
2694 {
2695     return range.stripLeft!pred().stripRight!pred();
2696 }
2697 
2698 /// ditto
2699 Range stripLeft(Range, E)(Range range, E element)
2700 if (isInputRange!Range && is(typeof(range.front == element) : bool))
2701 {
2702     import std.algorithm.searching : find;
2703     return find!((auto ref a) => a != element)(range);
2704 }
2705 
2706 /// ditto
2707 Range stripLeft(alias pred, Range)(Range range)
2708 if (isInputRange!Range && is(typeof(pred(range.front)) : bool))
2709 {
2710     import std.algorithm.searching : find;
2711     import std.functional : not;
2712 
2713     return find!(not!pred)(range);
2714 }
2715 
2716 /// ditto
2717 Range stripRight(Range, E)(Range range, E element)
2718 if (isBidirectionalRange!Range && is(typeof(range.back == element) : bool))
2719 {
2720     for (; !range.empty; range.popBack())
2721     {
2722         if (range.back != element)
2723             break;
2724     }
2725     return range;
2726 }
2727 
2728 /// ditto
2729 Range stripRight(alias pred, Range)(Range range)
2730 if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool))
2731 {
2732     for (; !range.empty; range.popBack())
2733     {
2734         if (!pred(range.back))
2735             break;
2736     }
2737     return range;
2738 }
2739 
2740 /// Strip leading and trailing elements equal to the target element.
2741 @safe pure unittest
2742 {
2743     assert("  foobar  ".strip(' ') == "foobar");
2744     assert("00223.444500".strip('0') == "223.4445");
2745     assert("ëëêéüŗōpéêëë".strip('ë') == "êéüŗōpéê");
2746     assert([1, 1, 0, 1, 1].strip(1) == [0]);
2747     assert([0.0, 0.01, 0.01, 0.0].strip(0).length == 2);
2748 }
2749 
2750 /// Strip leading and trailing elements while the predicate returns true.
2751 @safe pure unittest
2752 {
2753     assert("  foobar  ".strip!(a => a == ' ')() == "foobar");
2754     assert("00223.444500".strip!(a => a == '0')() == "223.4445");
2755     assert("ëëêéüŗōpéêëë".strip!(a => a == 'ë')() == "êéüŗōpéê");
2756     assert([1, 1, 0, 1, 1].strip!(a => a == 1)() == [0]);
2757     assert([0.0, 0.01, 0.5, 0.6, 0.01, 0.0].strip!(a => a < 0.4)().length == 2);
2758 }
2759 
2760 /// Strip leading elements equal to the target element.
2761 @safe pure unittest
2762 {
2763     assert("  foobar  ".stripLeft(' ') == "foobar  ");
2764     assert("00223.444500".stripLeft('0') == "223.444500");
2765     assert("ůůűniçodêéé".stripLeft('ů') == "űniçodêéé");
2766     assert([1, 1, 0, 1, 1].stripLeft(1) == [0, 1, 1]);
2767     assert([0.0, 0.01, 0.01, 0.0].stripLeft(0).length == 3);
2768 }
2769 
2770 /// Strip leading elements while the predicate returns true.
2771 @safe pure unittest
2772 {
2773     assert("  foobar  ".stripLeft!(a => a == ' ')() == "foobar  ");
2774     assert("00223.444500".stripLeft!(a => a == '0')() == "223.444500");
2775     assert("ůůűniçodêéé".stripLeft!(a => a == 'ů')() == "űniçodêéé");
2776     assert([1, 1, 0, 1, 1].stripLeft!(a => a == 1)() == [0, 1, 1]);
2777     assert([0.0, 0.01, 0.10, 0.5, 0.6].stripLeft!(a => a < 0.4)().length == 2);
2778 }
2779 
2780 /// Strip trailing elements equal to the target element.
2781 @safe pure unittest
2782 {
2783     assert("  foobar  ".stripRight(' ') == "  foobar");
2784     assert("00223.444500".stripRight('0') == "00223.4445");
2785     assert("ùniçodêéé".stripRight('é') == "ùniçodê");
2786     assert([1, 1, 0, 1, 1].stripRight(1) == [1, 1, 0]);
2787     assert([0.0, 0.01, 0.01, 0.0].stripRight(0).length == 3);
2788 }
2789 
2790 /// Strip trailing elements while the predicate returns true.
2791 @safe pure unittest
2792 {
2793     assert("  foobar  ".stripRight!(a => a == ' ')() == "  foobar");
2794     assert("00223.444500".stripRight!(a => a == '0')() == "00223.4445");
2795     assert("ùniçodêéé".stripRight!(a => a == 'é')() == "ùniçodê");
2796     assert([1, 1, 0, 1, 1].stripRight!(a => a == 1)() == [1, 1, 0]);
2797     assert([0.0, 0.01, 0.10, 0.5, 0.6].stripRight!(a => a > 0.4)().length == 3);
2798 }
2799 
2800 // swap
2801 /**
2802 Swaps `lhs` and `rhs`. The instances `lhs` and `rhs` are moved in
2803 memory, without ever calling `opAssign`, nor any other function. `T`
2804 need not be assignable at all to be swapped.
2805 
2806 If `lhs` and `rhs` reference the same instance, then nothing is done.
2807 
2808 `lhs` and `rhs` must be mutable. If `T` is a struct or union, then
2809 its fields must also all be (recursively) mutable.
2810 
2811 Params:
2812     lhs = Data to be swapped with `rhs`.
2813     rhs = Data to be swapped with `lhs`.
2814 */
2815 void swap(T)(ref T lhs, ref T rhs) @trusted pure nothrow @nogc
2816 if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs))))
2817 {
2818     import std.traits : hasAliasing, hasElaborateAssign, isAssignable,
2819                         isStaticArray;
2820     static if (hasAliasing!T) if (!__ctfe)
2821     {
2822         import std.exception : doesPointTo;
2823         assert(!doesPointTo(lhs, lhs), "Swap: lhs internal pointer.");
2824         assert(!doesPointTo(rhs, rhs), "Swap: rhs internal pointer.");
2825         assert(!doesPointTo(lhs, rhs), "Swap: lhs points to rhs.");
2826         assert(!doesPointTo(rhs, lhs), "Swap: rhs points to lhs.");
2827     }
2828 
2829     static if (hasElaborateAssign!T || !isAssignable!T)
2830     {
2831         if (&lhs != &rhs)
2832         {
2833             // For structs with non-trivial assignment, move memory directly
2834             ubyte[T.sizeof] t = void;
2835             auto a = (cast(ubyte*) &lhs)[0 .. T.sizeof];
2836             auto b = (cast(ubyte*) &rhs)[0 .. T.sizeof];
2837             t[] = a[];
2838             a[] = b[];
2839             b[] = t[];
2840         }
2841     }
2842     else
2843     {
2844         //Avoid assigning overlapping arrays. Dynamic arrays are fine, because
2845         //it's their ptr and length properties which get assigned rather
2846         //than their elements when assigning them, but static arrays are value
2847         //types and therefore all of their elements get copied as part of
2848         //assigning them, which would be assigning overlapping arrays if lhs
2849         //and rhs were the same array.
2850         static if (isStaticArray!T)
2851         {
2852             if (lhs.ptr == rhs.ptr)
2853                 return;
2854         }
2855 
2856         // For non-elaborate-assign types, suffice to do the classic swap
2857         static if (__traits(hasCopyConstructor, T))
2858         {
2859             // don't invoke any elaborate constructors either
2860             T tmp = void;
2861             tmp = lhs;
2862         }
2863         else
2864             auto tmp = lhs;
2865         lhs = rhs;
2866         rhs = tmp;
2867     }
2868 }
2869 
2870 ///
2871 @safe unittest
2872 {
2873     // Swapping POD (plain old data) types:
2874     int a = 42, b = 34;
2875     swap(a, b);
2876     assert(a == 34 && b == 42);
2877 
2878     // Swapping structs with indirection:
2879     static struct S { int x; char c; int[] y; }
2880     S s1 = { 0, 'z', [ 1, 2 ] };
2881     S s2 = { 42, 'a', [ 4, 6 ] };
2882     swap(s1, s2);
2883     assert(s1.x == 42);
2884     assert(s1.c == 'a');
2885     assert(s1.y == [ 4, 6 ]);
2886 
2887     assert(s2.x == 0);
2888     assert(s2.c == 'z');
2889     assert(s2.y == [ 1, 2 ]);
2890 
2891     // Immutables cannot be swapped:
2892     immutable int imm1 = 1, imm2 = 2;
2893     static assert(!__traits(compiles, swap(imm1, imm2)));
2894 
2895     int c = imm1 + 0;
2896     int d = imm2 + 0;
2897     swap(c, d);
2898     assert(c == 2);
2899     assert(d == 1);
2900 }
2901 
2902 ///
2903 @safe unittest
2904 {
2905     // Non-copyable types can still be swapped.
2906     static struct NoCopy
2907     {
2908         this(this) { assert(0); }
2909         int n;
2910         string s;
2911     }
2912     NoCopy nc1, nc2;
2913     nc1.n = 127; nc1.s = "abc";
2914     nc2.n = 513; nc2.s = "uvwxyz";
2915 
2916     swap(nc1, nc2);
2917     assert(nc1.n == 513 && nc1.s == "uvwxyz");
2918     assert(nc2.n == 127 && nc2.s == "abc");
2919 
2920     swap(nc1, nc1);
2921     swap(nc2, nc2);
2922     assert(nc1.n == 513 && nc1.s == "uvwxyz");
2923     assert(nc2.n == 127 && nc2.s == "abc");
2924 
2925     // Types containing non-copyable fields can also be swapped.
2926     static struct NoCopyHolder
2927     {
2928         NoCopy noCopy;
2929     }
2930     NoCopyHolder h1, h2;
2931     h1.noCopy.n = 31; h1.noCopy.s = "abc";
2932     h2.noCopy.n = 65; h2.noCopy.s = null;
2933 
2934     swap(h1, h2);
2935     assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
2936     assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");
2937 
2938     swap(h1, h1);
2939     swap(h2, h2);
2940     assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
2941     assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");
2942 
2943     // Const types cannot be swapped.
2944     const NoCopy const1, const2;
2945     assert(const1.n == 0 && const2.n == 0);
2946     static assert(!__traits(compiles, swap(const1, const2)));
2947 }
2948 
2949 // https://issues.dlang.org/show_bug.cgi?id=4789
2950 @safe unittest
2951 {
2952     int[1] s = [1];
2953     swap(s, s);
2954 
2955     int[3] a = [1, 2, 3];
2956     swap(a[1], a[2]);
2957     assert(a == [1, 3, 2]);
2958 }
2959 
2960 @safe unittest
2961 {
2962     static struct NoAssign
2963     {
2964         int i;
2965         void opAssign(NoAssign) @disable;
2966     }
2967     auto s1 = NoAssign(1);
2968     auto s2 = NoAssign(2);
2969     swap(s1, s2);
2970     assert(s1.i == 2);
2971     assert(s2.i == 1);
2972 }
2973 
2974 @safe unittest
2975 {
2976     struct S
2977     {
2978         const int i;
2979         int i2 = 2;
2980         int i3 = 3;
2981     }
2982     S s;
2983     static assert(!__traits(compiles, swap(s, s)));
2984     swap(s.i2, s.i3);
2985     assert(s.i2 == 3);
2986     assert(s.i3 == 2);
2987 }
2988 
2989 // https://issues.dlang.org/show_bug.cgi?id=11853
2990 @safe unittest
2991 {
2992     import std.traits : isAssignable;
2993     alias T = Tuple!(int, double);
2994     static assert(isAssignable!T);
2995 }
2996 
2997 // https://issues.dlang.org/show_bug.cgi?id=12024
2998 @safe unittest
2999 {
3000     import std.datetime;
3001     SysTime a, b;
3002     swap(a, b);
3003 }
3004 
3005 // https://issues.dlang.org/show_bug.cgi?id=9975
3006 @system unittest
3007 {
3008     import std.exception : doesPointTo, mayPointTo;
3009     static struct S2
3010     {
3011         union
3012         {
3013             size_t sz;
3014             string s;
3015         }
3016     }
3017     S2 a , b;
3018     a.sz = -1;
3019     assert(!doesPointTo(a, b));
3020     assert( mayPointTo(a, b));
3021     swap(a, b);
3022 
3023     //Note: we can catch an error here, because there is no RAII in this test
3024     import std.exception : assertThrown;
3025     void* p, pp;
3026     p = &p;
3027     assertThrown!Error(move(p));
3028     assertThrown!Error(move(p, pp));
3029     assertThrown!Error(swap(p, pp));
3030 }
3031 
3032 @system unittest
3033 {
3034     static struct A
3035     {
3036         int* x;
3037         this(this) { x = new int; }
3038     }
3039     A a1, a2;
3040     swap(a1, a2);
3041 
3042     static struct B
3043     {
3044         int* x;
3045         void opAssign(B) { x = new int; }
3046     }
3047     B b1, b2;
3048     swap(b1, b2);
3049 }
3050 
3051 // issue 20732
3052 @safe unittest
3053 {
3054     static struct A
3055     {
3056         int x;
3057         this(scope ref return const A other)
3058         {
3059             import std.stdio;
3060             x = other.x;
3061             // note, struct functions inside @safe functions infer ALL
3062             // attributes, so the following 3 lines are meant to prevent this.
3063             new int; // prevent @nogc inference
3064             writeln("impure"); // prevent pure inference
3065             throw new Exception(""); // prevent nothrow inference
3066         }
3067     }
3068 
3069     A a1, a2;
3070     swap(a1, a2);
3071 
3072     A[1] a3, a4;
3073     swap(a3, a4);
3074 }
3075 
3076 /// ditto
3077 void swap(T)(ref T lhs, ref T rhs)
3078 if (is(typeof(lhs.proxySwap(rhs))))
3079 {
3080     lhs.proxySwap(rhs);
3081 }
3082 
3083 /**
3084 Swaps two elements in-place of a range `r`,
3085 specified by their indices `i1` and `i2`.
3086 
3087 Params:
3088     r  = a range with swappable elements
3089     i1 = first index
3090     i2 = second index
3091 */
3092 void swapAt(R)(auto ref R r, size_t i1, size_t i2)
3093 {
3094     static if (is(typeof(&r.swapAt)))
3095     {
3096         r.swapAt(i1, i2);
3097     }
3098     else static if (is(typeof(&r[i1])))
3099     {
3100         swap(r[i1], r[i2]);
3101     }
3102     else
3103     {
3104         if (i1 == i2) return;
3105         auto t1 = r.moveAt(i1);
3106         auto t2 = r.moveAt(i2);
3107         r[i2] = t1;
3108         r[i1] = t2;
3109     }
3110 }
3111 
3112 ///
3113 pure @safe nothrow unittest
3114 {
3115     import std.algorithm.comparison : equal;
3116     auto a = [1, 2, 3];
3117     a.swapAt(1, 2);
3118     assert(a.equal([1, 3, 2]));
3119 }
3120 
3121 pure @safe nothrow unittest
3122 {
3123     import std.algorithm.comparison : equal;
3124     auto a = [4, 5, 6];
3125     a.swapAt(1, 1);
3126     assert(a.equal([4, 5, 6]));
3127 }
3128 
3129 pure @safe nothrow unittest
3130 {
3131     // test non random access ranges
3132     import std.algorithm.comparison : equal;
3133     import std.array : array;
3134 
3135     char[] b = ['a', 'b', 'c'];
3136     b.swapAt(1, 2);
3137     assert(b.equal(['a', 'c', 'b']));
3138 
3139     int[3] c = [1, 2, 3];
3140     c.swapAt(1, 2);
3141     assert(c.array.equal([1, 3, 2]));
3142 
3143     // opIndex returns lvalue
3144     struct RandomIndexType(T)
3145     {
3146         T payload;
3147 
3148         @property ref auto opIndex(size_t i)
3149         {
3150            return payload[i];
3151         }
3152 
3153     }
3154     auto d = RandomIndexType!(int[])([4, 5, 6]);
3155     d.swapAt(1, 2);
3156     assert(d.payload.equal([4, 6, 5]));
3157 
3158     // custom moveAt and opIndexAssign
3159     struct RandomMoveAtType(T)
3160     {
3161         T payload;
3162 
3163         ElementType!T moveAt(size_t i)
3164         {
3165            return payload.moveAt(i);
3166         }
3167 
3168         void opIndexAssign(ElementType!T val, size_t idx)
3169         {
3170             payload[idx] = val;
3171         }
3172     }
3173     auto e = RandomMoveAtType!(int[])([7, 8, 9]);
3174     e.swapAt(1, 2);
3175     assert(e.payload.equal([7, 9, 8]));
3176 
3177 
3178     // custom swapAt
3179     struct RandomSwapAtType(T)
3180     {
3181         T payload;
3182 
3183         void swapAt(size_t i)
3184         {
3185            return payload.swapAt(i);
3186         }
3187     }
3188     auto f = RandomMoveAtType!(int[])([10, 11, 12]);
3189     swapAt(f, 1, 2);
3190     assert(f.payload.equal([10, 12, 11]));
3191 }
3192 
3193 private void swapFront(R1, R2)(R1 r1, R2 r2)
3194 if (isInputRange!R1 && isInputRange!R2)
3195 {
3196     static if (is(typeof(swap(r1.front, r2.front))))
3197     {
3198         swap(r1.front, r2.front);
3199     }
3200     else
3201     {
3202         auto t1 = moveFront(r1), t2 = moveFront(r2);
3203         r1.front = move(t2);
3204         r2.front = move(t1);
3205     }
3206 }
3207 
3208 // swapRanges
3209 /**
3210 Swaps all elements of `r1` with successive elements in `r2`.
3211 Returns a tuple containing the remainder portions of `r1` and $(D
3212 r2) that were not swapped (one of them will be empty). The ranges may
3213 be of different types but must have the same element type and support
3214 swapping.
3215 
3216 Params:
3217     r1 = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3218          with swappable elements
3219     r2 = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3220          with swappable elements
3221 
3222 Returns:
3223     Tuple containing the remainder portions of r1 and r2 that were not swapped
3224 */
3225 Tuple!(InputRange1, InputRange2)
3226 swapRanges(InputRange1, InputRange2)(InputRange1 r1, InputRange2 r2)
3227 if (hasSwappableElements!InputRange1 && hasSwappableElements!InputRange2
3228     && is(ElementType!InputRange1 == ElementType!InputRange2))
3229 {
3230     for (; !r1.empty && !r2.empty; r1.popFront(), r2.popFront())
3231     {
3232         swap(r1.front, r2.front);
3233     }
3234     return tuple(r1, r2);
3235 }
3236 
3237 ///
3238 @safe unittest
3239 {
3240     import std.range : empty;
3241     int[] a = [ 100, 101, 102, 103 ];
3242     int[] b = [ 0, 1, 2, 3 ];
3243     auto c = swapRanges(a[1 .. 3], b[2 .. 4]);
3244     assert(c[0].empty && c[1].empty);
3245     assert(a == [ 100, 2, 3, 103 ]);
3246     assert(b == [ 0, 1, 101, 102 ]);
3247 }
3248 
3249 /**
3250 Initializes each element of `range` with `value`.
3251 Assumes that the elements of the range are uninitialized.
3252 This is of interest for structs that
3253 define copy constructors (for all other types, $(LREF fill) and
3254 uninitializedFill are equivalent).
3255 
3256 Params:
3257         range = An
3258                 $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3259                 that exposes references to its elements and has assignable
3260                 elements
3261         value = Assigned to each element of range
3262 
3263 See_Also:
3264         $(LREF fill)
3265         $(LREF initializeAll)
3266  */
3267 void uninitializedFill(Range, Value)(Range range, Value value)
3268 if (isInputRange!Range && hasLvalueElements!Range && is(typeof(range.front = value)))
3269 {
3270     import std.traits : hasElaborateAssign;
3271 
3272     alias T = ElementType!Range;
3273     static if (hasElaborateAssign!T)
3274     {
3275         import core.internal.lifetime : emplaceRef;
3276 
3277         // Must construct stuff by the book
3278         for (; !range.empty; range.popFront())
3279             emplaceRef!T(range.front, value);
3280     }
3281     else
3282         // Doesn't matter whether fill is initialized or not
3283         return fill(range, value);
3284 }
3285 
3286 ///
3287 nothrow @system unittest
3288 {
3289     import core.stdc.stdlib : malloc, free;
3290 
3291     auto s = (cast(int*) malloc(5 * int.sizeof))[0 .. 5];
3292     uninitializedFill(s, 42);
3293     assert(s == [ 42, 42, 42, 42, 42 ]);
3294 
3295     scope(exit) free(s.ptr);
3296 }
3297