1 /**
2 This module is a submodule of $(MREF std, range).
3 
4 It defines the bidirectional and forward range primitives for arrays:
5 $(LREF empty), $(LREF front), $(LREF back), $(LREF popFront), $(LREF popBack) and $(LREF save).
6 
7 It provides basic range functionality by defining several templates for testing
8 whether a given object is a range, and what kind of range it is:
9 
10 $(SCRIPT inhibitQuickIndex = 1;)
11 $(DIVC quickindex,
12 $(BOOKTABLE ,
13     $(TR $(TD $(LREF isInputRange))
14         $(TD Tests if something is an $(I input range), defined to be
15         something from which one can sequentially read data using the
16         primitives `front`, `popFront`, and `empty`.
17     ))
18     $(TR $(TD $(LREF isOutputRange))
19         $(TD Tests if something is an $(I output range), defined to be
20         something to which one can sequentially write data using the
21         $(LREF put) primitive.
22     ))
23     $(TR $(TD $(LREF isForwardRange))
24         $(TD Tests if something is a $(I forward range), defined to be an
25         input range with the additional capability that one can save one's
26         current position with the `save` primitive, thus allowing one to
27         iterate over the same range multiple times.
28     ))
29     $(TR $(TD $(LREF isBidirectionalRange))
30         $(TD Tests if something is a $(I bidirectional range), that is, a
31         forward range that allows reverse traversal using the primitives $(D
32         back) and `popBack`.
33     ))
34     $(TR $(TD $(LREF isRandomAccessRange))
35         $(TD Tests if something is a $(I random access range), which is a
36         bidirectional range that also supports the array subscripting
37         operation via the primitive `opIndex`.
38     ))
39 ))
40 
41 It also provides number of templates that test for various range capabilities:
42 
43 $(BOOKTABLE ,
44     $(TR $(TD $(LREF hasMobileElements))
45         $(TD Tests if a given range's elements can be moved around using the
46         primitives `moveFront`, `moveBack`, or `moveAt`.
47     ))
48     $(TR $(TD $(LREF ElementType))
49         $(TD Returns the element type of a given range.
50     ))
51     $(TR $(TD $(LREF ElementEncodingType))
52         $(TD Returns the encoding element type of a given range.
53     ))
54     $(TR $(TD $(LREF hasSwappableElements))
55         $(TD Tests if a range is a forward range with swappable elements.
56     ))
57     $(TR $(TD $(LREF hasAssignableElements))
58         $(TD Tests if a range is a forward range with mutable elements.
59     ))
60     $(TR $(TD $(LREF hasLvalueElements))
61         $(TD Tests if a range is a forward range with elements that can be
62         passed by reference and have their address taken.
63     ))
64     $(TR $(TD $(LREF hasLength))
65         $(TD Tests if a given range has the `length` attribute.
66     ))
67     $(TR $(TD $(LREF isInfinite))
68         $(TD Tests if a given range is an $(I infinite range).
69     ))
70     $(TR $(TD $(LREF hasSlicing))
71         $(TD Tests if a given range supports the array slicing operation $(D
72         R[x .. y]).
73     ))
74 )
75 
76 Finally, it includes some convenience functions for manipulating ranges:
77 
78 $(BOOKTABLE ,
79     $(TR $(TD $(LREF popFrontN))
80         $(TD Advances a given range by up to $(I n) elements.
81     ))
82     $(TR $(TD $(LREF popBackN))
83         $(TD Advances a given bidirectional range from the right by up to
84         $(I n) elements.
85     ))
86     $(TR $(TD $(LREF popFrontExactly))
87         $(TD Advances a given range by up exactly $(I n) elements.
88     ))
89     $(TR $(TD $(LREF popBackExactly))
90         $(TD Advances a given bidirectional range from the right by exactly
91         $(I n) elements.
92     ))
93     $(TR $(TD $(LREF moveFront))
94         $(TD Removes the front element of a range.
95     ))
96     $(TR $(TD $(LREF moveBack))
97         $(TD Removes the back element of a bidirectional range.
98     ))
99     $(TR $(TD $(LREF moveAt))
100         $(TD Removes the $(I i)'th element of a random-access range.
101     ))
102     $(TR $(TD $(LREF walkLength))
103         $(TD Computes the length of any range in O(n) time.
104     ))
105     $(TR $(TD $(LREF put))
106         $(TD Outputs element `e` to a range.
107     ))
108 )
109 
110 Source: $(PHOBOSSRC std/range/primitives.d)
111 
112 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
113 
114 Authors: $(HTTP erdani.com, Andrei Alexandrescu), David Simcha, and
115          $(HTTP jmdavisprog.com, Jonathan M Davis). Credit for some of the ideas
116          in building this module goes to
117          $(HTTP fantascienza.net/leonardo/so/, Leonardo Maffi).
118 */
119 module std.range.primitives;
120 
121 import std.traits;
122 
123 /**
124 Returns `true` if `R` is an input range. An input range must
125 define the primitives `empty`, `popFront`, and `front`. The
126 following code should compile for any input range.
127 
128 ----
129 R r;              // can define a range object
130 if (r.empty) {}   // can test for empty
131 r.popFront();     // can invoke popFront()
132 auto h = r.front; // can get the front of the range of non-void type
133 ----
134 
135 The following are rules of input ranges are assumed to hold true in all
136 Phobos code. These rules are not checkable at compile-time, so not conforming
137 to these rules when writing ranges or range based code will result in
138 undefined behavior.
139 
140 $(UL
141     $(LI `r.empty` returns `false` if and only if there is more data
142     available in the range.)
143     $(LI `r.empty` evaluated multiple times, without calling
144     `r.popFront`, or otherwise mutating the range object or the
145     underlying data, yields the same result for every evaluation.)
146     $(LI `r.front` returns the current element in the range.
147     It may return by value or by reference.)
148     $(LI `r.front` can be legally evaluated if and only if evaluating
149     `r.empty` has, or would have, equaled `false`.)
150     $(LI `r.front` evaluated multiple times, without calling
151     `r.popFront`, or otherwise mutating the range object or the
152     underlying data, yields the same result for every evaluation.)
153     $(LI `r.popFront` advances to the next element in the range.)
154     $(LI `r.popFront` can be called if and only if evaluating `r.empty`
155     has, or would have, equaled `false`.)
156 )
157 
158 Also, note that Phobos code assumes that the primitives `r.front` and
159 `r.empty` are $(BIGOH 1) time complexity wise or "cheap" in terms of
160 running time. $(BIGOH) statements in the documentation of range functions
161 are made with this assumption.
162 
163 See_Also:
164     The header of $(MREF std,range) for tutorials on ranges.
165 
166 Params:
167     R = type to be tested
168     E = if present, the elements of the range must be
169         $(DDSUBLINK spec/const3, implicit_qualifier_conversions, qualifier-convertible)
170         to this type
171 
172 Returns:
173     `true` if R is an input range (possibly with element type `E`), `false` if not
174  */
175 enum bool isInputRange(R) =
176     is(typeof(R.init) == R)
177     && is(typeof((R r) { return r.empty; } (R.init)) == bool)
178     && (is(typeof((return ref R r) => r.front)) || is(typeof(ref (return ref R r) => r.front)))
179     && !is(typeof((R r) { return r.front; } (R.init)) == void)
180     && is(typeof((R r) => r.popFront));
181 
182 /// ditto
183 enum bool isInputRange(R, E) =
184     .isInputRange!R && isQualifierConvertible!(ElementType!R, E);
185 
186 ///
187 @safe unittest
188 {
189     struct A {}
190     struct B
191     {
192         void popFront();
193         @property bool empty();
194         @property int front();
195     }
196     static assert(!isInputRange!A);
197     static assert( isInputRange!B);
198     static assert( isInputRange!(int[]));
199     static assert( isInputRange!(char[]));
200     static assert(!isInputRange!(char[4]));
201     static assert( isInputRange!(inout(int)[]));
202     static assert(!isInputRange!(int[], string));
203     static assert( isInputRange!(int[], int));
204     static assert( isInputRange!(int[], const int));
205     static assert(!isInputRange!(int[], immutable int));
206 
207     static assert(!isInputRange!(const(int)[], int));
208     static assert( isInputRange!(const(int)[], const int));
209     static assert(!isInputRange!(const(int)[], immutable int));
210 
211     static assert(!isInputRange!(immutable(int)[], int));
212     static assert( isInputRange!(immutable(int)[], const int));
213     static assert( isInputRange!(immutable(int)[], immutable int));
214 
215     static struct NotDefaultConstructible
216     {
217         @disable this();
218         void popFront();
219         @property bool empty();
220         @property int front();
221     }
222     static assert( isInputRange!NotDefaultConstructible);
223 
224     static struct NotDefaultConstructibleOrCopyable
225     {
226         @disable this();
227         @disable this(this);
228         void popFront();
229         @property bool empty();
230         @property int front();
231     }
232     static assert(isInputRange!NotDefaultConstructibleOrCopyable);
233 
234     static struct Frontless
235     {
236         void popFront();
237         @property bool empty();
238     }
239     static assert(!isInputRange!Frontless);
240 
241     static struct VoidFront
242     {
243         void popFront();
244         @property bool empty();
245         void front();
246     }
247     static assert(!isInputRange!VoidFront);
248 }
249 // https://issues.dlang.org/show_bug.cgi?id=16034
250 @safe unittest
251 {
252     struct One
253     {
254         int entry = 1;
255         @disable this(this);
256     }
257 
258     assert(isInputRange!(One[]));
259 }
260 
261 @safe unittest
262 {
263     import std.algorithm.comparison : equal;
264 
265     static struct R
266     {
267         static struct Front
268         {
269             R* impl;
270             @property int value() { return impl._front; }
271             alias value this;
272         }
273 
274         int _front;
275 
276         @property bool empty() { return _front >= 3; }
277         @property auto front() { return Front(&this); }
278         void popFront() { _front++; }
279     }
280     R r;
281 
282     static assert(isInputRange!R);
283     assert(r.equal([ 0, 1, 2 ]));
284 }
285 
286 /+
287 puts the whole raw element `e` into `r`. doPut will not attempt to
288 iterate, slice or transcode `e` in any way shape or form. It will $(B only)
289 call the correct primitive (`r.put(e)`,  $(D r.front = e) or
290 `r(e)` once.
291 
292 This can be important when `e` needs to be placed in `r` unchanged.
293 Furthermore, it can be useful when working with `InputRange`s, as doPut
294 guarantees that no more than a single element will be placed.
295 +/
296 private void doPut(R, E)(ref R r, auto ref E e)
297 {
298     static if (is(PointerTarget!R == struct))
299         enum usingPut = hasMember!(PointerTarget!R, "put");
300     else
301         enum usingPut = hasMember!(R, "put");
302 
303     static if (usingPut)
304     {
305         static assert(is(typeof(r.put(e))),
306             "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ ".");
307         r.put(e);
308     }
309     else static if (isNarrowString!R && is(const(E) == const(typeof(r[0]))))
310     {
311         // one character, we can put it
312         r[0] = e;
313         r = r[1 .. $];
314     }
315     else static if (isNarrowString!R && isNarrowString!E && is(typeof(r[] = e)))
316     {
317         // slice assign. Note that this is a duplicate from put, but because
318         // putChar uses doPut exclusively, we have to copy it here.
319         immutable len = e.length;
320         r[0 .. len] = e;
321         r = r[len .. $];
322     }
323     else static if (isInputRange!R)
324     {
325         static assert(is(typeof(r.front = e)),
326             "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ ".");
327         r.front = e;
328         r.popFront();
329     }
330     else static if (is(typeof(r(e))))
331     {
332         r(e);
333     }
334     else
335     {
336         static assert(false,
337             "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ ".");
338     }
339 }
340 
341 @safe unittest
342 {
343     static assert(!isNativeOutputRange!(int,     int));
344     static assert( isNativeOutputRange!(int[],   int));
345     static assert(!isNativeOutputRange!(int[][], int));
346 
347     static assert(!isNativeOutputRange!(int,     int[]));
348     static assert(!isNativeOutputRange!(int[],   int[]));
349     static assert( isNativeOutputRange!(int[][], int[]));
350 
351     static assert(!isNativeOutputRange!(int,     int[][]));
352     static assert(!isNativeOutputRange!(int[],   int[][]));
353     static assert(!isNativeOutputRange!(int[][], int[][]));
354 
355     static assert(!isNativeOutputRange!(int[4],   int));
356     static assert( isNativeOutputRange!(int[4][], int)); //Scary!
357     static assert( isNativeOutputRange!(int[4][], int[4]));
358 
359     static assert( isNativeOutputRange!( char[],   char));
360     static assert(!isNativeOutputRange!( char[],  dchar));
361     static assert( isNativeOutputRange!(dchar[],   char));
362     static assert( isNativeOutputRange!(dchar[],  dchar));
363 
364 }
365 
366 /++
367 Outputs `e` to `r`. The exact effect is dependent upon the two
368 types. Several cases are accepted, as described below. The code snippets
369 are attempted in order, and the first to compile "wins" and gets
370 evaluated.
371 
372 In this table "doPut" is a method that places `e` into `r`, using the
373 correct primitive: `r.put(e)` if `R` defines `put`, $(D r.front = e)
374 if `r` is an input range (followed by `r.popFront()`), or `r(e)`
375 otherwise.
376 
377 $(BOOKTABLE ,
378     $(TR
379         $(TH Code Snippet)
380         $(TH Scenario)
381     )
382     $(TR
383         $(TD `r.doPut(e);`)
384         $(TD `R` specifically accepts an `E`.)
385     )
386     $(TR
387         $(TD $(D r.doPut([ e ]);))
388         $(TD `R` specifically accepts an `E[]`.)
389     )
390     $(TR
391         $(TD `r.putChar(e);`)
392         $(TD `R` accepts some form of string or character. put will
393             transcode the character `e` accordingly.)
394     )
395     $(TR
396         $(TD $(D for (; !e.empty; e.popFront()) put(r, e.front);))
397         $(TD Copying range `E` into `R`.)
398     )
399 )
400 
401 Tip: `put` should $(I not) be used "UFCS-style", e.g. `r.put(e)`.
402 Doing this may call `R.put` directly, by-passing any transformation
403 feature provided by `Range.put`. $(D put(r, e)) is prefered.
404  +/
405 void put(R, E)(ref R r, E e)
406 {
407     //First level: simply straight up put.
408     static if (is(typeof(doPut(r, e))))
409     {
410         doPut(r, e);
411     }
412     //Optional optimization block for straight up array to array copy.
413     else static if (isDynamicArray!R &&
414                     !isAutodecodableString!R &&
415                     isDynamicArray!E &&
416                     is(typeof(r[] = e[])))
417     {
418         immutable len = e.length;
419         r[0 .. len] = e[];
420         r = r[len .. $];
421     }
422     //Accepts E[] ?
423     else static if (is(typeof(doPut(r, [e]))) && !isDynamicArray!R)
424     {
425         if (__ctfe)
426         {
427             E[1] arr = [e];
428             doPut(r, arr[]);
429         }
430         else
431             doPut(r, (ref e) @trusted { return (&e)[0 .. 1]; }(e));
432     }
433     //special case for char to string.
434     else static if (isSomeChar!E && is(typeof(putChar(r, e))))
435     {
436         putChar(r, e);
437     }
438     //Extract each element from the range
439     //We can use "put" here, so we can recursively test a RoR of E.
440     else static if (isInputRange!E && is(typeof(put(r, e.front))))
441     {
442         //Special optimization: If E is a narrow string, and r accepts characters no-wider than the string's
443         //Then simply feed the characters 1 by 1.
444         static if (isAutodecodableString!E && !isAggregateType!E && (
445             (is(E : const  char[]) && is(typeof(doPut(r,  char.max))) && !is(typeof(doPut(r, dchar.max))) &&
446                 !is(typeof(doPut(r, wchar.max)))) ||
447             (is(E : const wchar[]) && is(typeof(doPut(r, wchar.max))) && !is(typeof(doPut(r, dchar.max)))) ) )
448         {
449             foreach (c; e)
450                 doPut(r, c);
451         }
452         else
453         {
454             for (; !e.empty; e.popFront())
455                 put(r, e.front);
456         }
457     }
458     else
459     {
460         static assert(false, "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ ".");
461     }
462 }
463 
464 /**
465  * When an output range's `put` method only accepts elements of type
466  * `T`, use the global `put` to handle outputting a `T[]` to the range
467  * or vice-versa.
468  */
469 @safe pure unittest
470 {
471     import std.traits : isSomeChar;
472 
473     static struct A
474     {
475         string data;
476 
477         void put(C)(C c) if (isSomeChar!C)
478         {
479             data ~= c;
480         }
481     }
482     static assert(isOutputRange!(A, char));
483 
484     auto a = A();
485     put(a, "Hello");
486     assert(a.data == "Hello");
487 }
488 
489 /**
490  * `put` treats dynamic arrays as array slices, and will call `popFront`
491  * on the slice after an element has been copied.
492  *
493  * Be sure to save the position of the array before calling `put`.
494  */
495 @safe pure nothrow unittest
496 {
497     int[] a = [1, 2, 3], b = [10, 20];
498     auto c = a;
499     put(a, b);
500     assert(c == [10, 20, 3]);
501     // at this point, a was advanced twice, so it only contains
502     // its last element while c represents the whole array
503     assert(a == [3]);
504 }
505 
506 /**
507  * It's also possible to `put` any width strings or characters into narrow
508  * strings -- put does the conversion for you.
509  *
510  * Note that putting the same width character as the target buffer type is
511  * `nothrow`, but transcoding can throw a $(REF UTFException, std, utf).
512  */
513 @safe pure unittest
514 {
515     // the elements must be mutable, so using string or const(char)[]
516     // won't compile
517     char[] s1 = new char[13];
518     auto r1 = s1;
519     put(r1, "Hello, World!"w);
520     assert(s1 == "Hello, World!");
521 }
522 
523 @safe pure nothrow unittest
524 {
525     // same thing, just using same character width.
526     char[] s1 = new char[13];
527     auto r1 = s1;
528     put(r1, "Hello, World!");
529     assert(s1 == "Hello, World!");
530 }
531 
532 
533 @safe pure nothrow @nogc unittest
534 {
535     static struct R() { void put(scope const(char)[]) {} }
536     R!() r;
537     put(r, 'a');
538 }
539 
540 //Helper function to handle chars as quickly and as elegantly as possible
541 //Assumes r.put(e)/r(e) has already been tested
542 private void putChar(R, E)(ref R r, E e)
543 if (isSomeChar!E)
544 {
545     // https://issues.dlang.org/show_bug.cgi?id=9186: Can't use (E[]).init
546     enum csCond = is(typeof(doPut(r, (){ ref const( char)[] cstringInit(); return cstringInit(); }())));
547     enum wsCond = is(typeof(doPut(r, (){ ref const(wchar)[] wstringInit(); return wstringInit(); }())));
548     enum dsCond = is(typeof(doPut(r, (){ ref const(dchar)[] dstringInit(); return dstringInit(); }())));
549 
550     //Use "max" to avoid static type demotion
551     enum ccCond = is(typeof(doPut(r,  char.max)));
552     enum wcCond = is(typeof(doPut(r, wchar.max)));
553     //enum dcCond = is(typeof(doPut(r, dchar.max)));
554 
555     //Fast transform a narrow char into a wider string
556     static if ((wsCond && E.sizeof < wchar.sizeof) || (dsCond && E.sizeof < dchar.sizeof))
557     {
558         enum w = wsCond && E.sizeof < wchar.sizeof;
559         Select!(w, wchar, dchar) c = e;
560         typeof(c)[1] arr = [c];
561         doPut(r, arr[]);
562     }
563     //Encode a wide char into a narrower string
564     else static if (wsCond || csCond)
565     {
566         import std.utf : encode;
567         /+static+/ Select!(wsCond, wchar[2], char[4]) buf; //static prevents purity.
568         doPut(r, buf[0 .. encode(buf, e)]);
569     }
570     //Slowly encode a wide char into a series of narrower chars
571     else static if (wcCond || ccCond)
572     {
573         import std.encoding : encode;
574         alias C = Select!(wcCond, wchar, char);
575         encode!(C, R)(e, r);
576     }
577     else
578     {
579         static assert(false, "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ ".");
580     }
581 }
582 
583 pure @safe unittest
584 {
585     auto f = delegate (const(char)[]) {};
586     putChar(f, cast(dchar)'a');
587 }
588 
589 
590 @safe pure unittest
591 {
592     static struct R() { void put(scope const(char)[]) {} }
593     R!() r;
594     putChar(r, 'a');
595 }
596 
597 @safe unittest
598 {
599     struct A {}
600     static assert(!isInputRange!(A));
601     struct B
602     {
603         void put(int) {}
604     }
605     B b;
606     put(b, 5);
607 }
608 
609 @safe unittest
610 {
611     int[] a = new int[10];
612     int b;
613     static assert(isInputRange!(typeof(a)));
614     put(a, b);
615 }
616 
617 @safe unittest
618 {
619     void myprint(scope const(char)[] s) { }
620     auto r = &myprint;
621     put(r, 'a');
622 }
623 
624 @safe unittest
625 {
626     int[] a = new int[10];
627     static assert(!__traits(compiles, put(a, 1.0L)));
628     put(a, 1);
629     assert(a.length == 9);
630     /*
631      * a[0] = 65;       // OK
632      * a[0] = 'A';      // OK
633      * a[0] = "ABC"[0]; // OK
634      * put(a, "ABC");   // OK
635      */
636     put(a, "ABC");
637     assert(a.length == 6);
638 }
639 
640 @safe unittest
641 {
642     char[] a = new char[10];
643     static assert(!__traits(compiles, put(a, 1.0L)));
644     static assert(!__traits(compiles, put(a, 1)));
645     //char[] is now an output range for char, wchar, dchar, and ranges of such.
646     static assert(__traits(compiles, putChar(a, 'a')));
647     static assert(__traits(compiles, put(a, wchar('a'))));
648     static assert(__traits(compiles, put(a, dchar('a'))));
649     static assert(__traits(compiles, put(a, "ABC")));
650     static assert(__traits(compiles, put(a, "ABC"w)));
651     static assert(__traits(compiles, put(a, "ABC"d)));
652 }
653 
654 @safe unittest
655 {
656     // attempt putting into narrow strings by transcoding
657     char[] a = new char[10];
658     auto b = a;
659     put(a, "ABC"w);
660     assert(b[0 .. 3] == "ABC");
661     assert(a.length == 7);
662 
663     a = b; // reset
664     put(a, 'λ');
665     assert(b[0 .. 2] == "λ");
666     assert(a.length == 8);
667 
668     a = b; // reset
669     put(a, "ABC"d);
670     assert(b[0 .. 3] == "ABC");
671     assert(a.length == 7);
672 
673     a = b; // reset
674     put(a, '𐐷');
675     assert(b[0 .. 4] == "𐐷");
676     assert(a.length == 6);
677 
678     wchar[] aw = new wchar[10];
679     auto bw = aw;
680     put(aw, "ABC");
681     assert(bw[0 .. 3] == "ABC"w);
682     assert(aw.length == 7);
683 
684     aw = bw; // reset
685     put(aw, 'λ');
686     assert(bw[0 .. 1] == "λ"w);
687     assert(aw.length == 9);
688 
689     aw = bw; // reset
690     put(aw, "ABC"d);
691     assert(bw[0 .. 3] == "ABC"w);
692     assert(aw.length == 7);
693 
694     aw = bw; // reset
695     put(aw, '𐐷');
696     assert(bw[0 .. 2] == "𐐷"w);
697     assert(aw.length == 8);
698 
699     aw = bw; // reset
700     put(aw, "𐐷"); // try transcoding from char[]
701     assert(bw[0 .. 2] == "𐐷"w);
702     assert(aw.length == 8);
703 }
704 
705 @safe unittest
706 {
707     int[][] a = new int[][10];
708     int[]   b = new int[10];
709     int     c;
710     put(b, c);
711     assert(b.length == 9);
712     put(a, b);
713     assert(a.length == 9);
714     static assert(!__traits(compiles, put(a, c)));
715 }
716 
717 @safe unittest
718 {
719     int[][] a = new int[][](3);
720     int[]   b = [1];
721     auto aa = a;
722     put(aa, b);
723     assert(aa == [[], []]);
724     assert(a  == [[1], [], []]);
725     int[][3] c = [2];
726     aa = a;
727     put(aa, c[]);
728     assert(aa.empty);
729     assert(a == [[2], [2], [2]]);
730 }
731 
732 @safe unittest
733 {
734     // Test fix for bug 7476.
735     struct LockingTextWriter
736     {
737         void put(dchar c){}
738     }
739     struct RetroResult
740     {
741         bool end = false;
742         @property bool empty() const { return end; }
743         @property dchar front(){ return 'a'; }
744         void popFront(){ end = true; }
745     }
746     LockingTextWriter w;
747     RetroResult re;
748     put(w, re);
749 }
750 
751 @system unittest
752 {
753     import std.conv : to;
754     import std.meta : AliasSeq;
755     import std.typecons : tuple;
756 
757     static struct PutC(C)
758     {
759         string result;
760         void put(const(C) c) { result ~= to!string((&c)[0 .. 1]); }
761     }
762     static struct PutS(C)
763     {
764         string result;
765         void put(const(C)[] s) { result ~= to!string(s); }
766     }
767     static struct PutSS(C)
768     {
769         string result;
770         void put(const(C)[][] ss)
771         {
772             foreach (s; ss)
773                 result ~= to!string(s);
774         }
775     }
776 
777     PutS!char p;
778     putChar(p, cast(dchar)'a');
779 
780     //Source Char
781     static foreach (SC; AliasSeq!(char, wchar, dchar))
782     {{
783         SC ch = 'I';
784         dchar dh = '♥';
785         immutable(SC)[] s = "日本語!";
786         immutable(SC)[][] ss = ["日本語", "が", "好き", "ですか", "?"];
787 
788         //Target Char
789         static foreach (TC; AliasSeq!(char, wchar, dchar))
790         {
791             //Testing PutC and PutS
792             static foreach (Type; AliasSeq!(PutC!TC, PutS!TC))
793             {{
794                 Type type;
795                 auto sink = new Type();
796 
797                 //Testing put and sink
798                 foreach (value ; tuple(type, sink))
799                 {
800                     put(value, ch);
801                     assert(value.result == "I");
802                     put(value, dh);
803                     assert(value.result == "I♥");
804                     put(value, s);
805                     assert(value.result == "I♥日本語!");
806                     put(value, ss);
807                     assert(value.result == "I♥日本語!日本語が好きですか?");
808                 }
809             }}
810         }
811     }}
812 }
813 
814 @safe unittest
815 {
816     static struct CharRange
817     {
818         char c;
819         enum empty = false;
820         void popFront(){}
821         ref char front() return @property
822         {
823             return c;
824         }
825     }
826     CharRange c;
827     put(c, cast(dchar)'H');
828     put(c, "hello"d);
829 }
830 
831 // https://issues.dlang.org/show_bug.cgi?id=9823
832 @system unittest
833 {
834     const(char)[] r;
835     void delegate(const(char)[]) dg = (s) { r = s; };
836     put(dg, ["ABC"]);
837     assert(r == "ABC");
838 }
839 
840 // https://issues.dlang.org/show_bug.cgi?id=10571
841 @safe unittest
842 {
843     import std.format.write : formattedWrite;
844     string buf;
845     formattedWrite((scope const(char)[] s) { buf ~= s; }, "%s", "hello");
846     assert(buf == "hello");
847 }
848 
849 @safe unittest
850 {
851     import std.format.write : formattedWrite;
852     import std.meta : AliasSeq;
853     struct PutC(C)
854     {
855         void put(C){}
856     }
857     struct PutS(C)
858     {
859         void put(const(C)[]){}
860     }
861     struct CallC(C)
862     {
863         void opCall(C){}
864     }
865     struct CallS(C)
866     {
867         void opCall(const(C)[]){}
868     }
869     struct FrontC(C)
870     {
871         enum empty = false;
872         auto front()@property{return C.init;}
873         void front(C)@property{}
874         void popFront(){}
875     }
876     struct FrontS(C)
877     {
878         enum empty = false;
879         auto front()@property{return C[].init;}
880         void front(const(C)[])@property{}
881         void popFront(){}
882     }
883     void foo()
884     {
885         static foreach (C; AliasSeq!(char, wchar, dchar))
886         {{
887             formattedWrite((C c){},        "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
888             formattedWrite((const(C)[]){}, "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
889             formattedWrite(PutC!C(),       "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
890             formattedWrite(PutS!C(),       "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
891             CallC!C callC;
892             CallS!C callS;
893             formattedWrite(callC,          "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
894             formattedWrite(callS,          "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
895             formattedWrite(FrontC!C(),     "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
896             formattedWrite(FrontS!C(),     "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
897         }}
898         formattedWrite((dchar[]).init,     "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
899     }
900 }
901 
902 /+
903 Returns `true` if `R` is a native output range for elements of type
904 `E`. An output range is defined functionally as a range that
905 supports the operation $(D doPut(r, e)) as defined above. if $(D doPut(r, e))
906 is valid, then `put(r,e)` will have the same behavior.
907 
908 The two guarantees isNativeOutputRange gives over the larger `isOutputRange`
909 are:
910 1: `e` is $(B exactly) what will be placed (not `[e]`, for example).
911 2: if `E` is a non $(empty) `InputRange`, then placing `e` is
912 guaranteed to not overflow the range.
913  +/
914 package(std) enum bool isNativeOutputRange(R, E) =
915     is(typeof(doPut(lvalueOf!R, lvalueOf!E)));
916 
917 @safe unittest
918 {
919     int[] r = new int[](4);
920     static assert(isInputRange!(int[]));
921     static assert( isNativeOutputRange!(int[], int));
922     static assert(!isNativeOutputRange!(int[], int[]));
923     static assert( isOutputRange!(int[], int[]));
924 
925     if (!r.empty)
926         put(r, 1); //guaranteed to succeed
927     if (!r.empty)
928         put(r, [1, 2]); //May actually error out.
929 }
930 
931 /++
932 Returns `true` if `R` is an output range for elements of type
933 `E`. An output range is defined functionally as a range that
934 supports the operation $(D put(r, e)) as defined above.
935 
936 See_Also:
937     The header of $(MREF std,range) for tutorials on ranges.
938  +/
939 enum bool isOutputRange(R, E) =
940     is(typeof(put(lvalueOf!R, lvalueOf!E)));
941 
942 ///
943 @safe unittest
944 {
945     void myprint(scope const(char)[] s) { }
946     static assert(isOutputRange!(typeof(&myprint), char));
947 
948     static assert( isOutputRange!(char[], char));
949     static assert( isOutputRange!(dchar[], wchar));
950     static assert( isOutputRange!(dchar[], dchar));
951 }
952 
953 @safe unittest
954 {
955     import std.array;
956     import std.stdio : writeln;
957 
958     auto app = appender!string();
959     string s;
960     static assert( isOutputRange!(Appender!string, string));
961     static assert( isOutputRange!(Appender!string*, string));
962     static assert(!isOutputRange!(Appender!string, int));
963     static assert( isOutputRange!(wchar[], wchar));
964     static assert( isOutputRange!(dchar[], char));
965     static assert( isOutputRange!(dchar[], string));
966     static assert( isOutputRange!(dchar[], wstring));
967     static assert( isOutputRange!(dchar[], dstring));
968 
969     static assert(!isOutputRange!(const(int)[], int));
970     static assert(!isOutputRange!(inout(int)[], int));
971 }
972 
973 
974 /**
975 Returns `true` if `R` is a forward range. A forward range is an
976 input range `r` that can save "checkpoints" by saving `r.save`
977 to another value of type `R`. Notable examples of input ranges that
978 are $(I not) forward ranges are file/socket ranges; copying such a
979 range will not save the position in the stream, and they most likely
980 reuse an internal buffer as the entire stream does not sit in
981 memory. Subsequently, advancing either the original or the copy will
982 advance the stream, so the copies are not independent.
983 
984 The following code should compile for any forward range.
985 
986 ----
987 static assert(isInputRange!R);
988 R r1;
989 auto s1 = r1.save;
990 static assert(is(typeof(s1) == R));
991 ----
992 
993 Saving a range is not duplicating it; in the example above, `r1`
994 and `r2` still refer to the same underlying data. They just
995 navigate that data independently.
996 
997 The semantics of a forward range (not checkable during compilation)
998 are the same as for an input range, with the additional requirement
999 that backtracking must be possible by saving a copy of the range
1000 object with `save` and using it later.
1001 
1002 `save` behaves in many ways like a copy constructor, and its
1003 implementation typically is done using copy construction.
1004 
1005 The existence of a copy constructor, however, does not imply
1006 the range is a forward range. For example, a range that reads
1007 from a TTY consumes its input and cannot save its place and
1008 read it again, and so cannot be a forward range and cannot
1009 have a `save` function.
1010 
1011 
1012 See_Also:
1013     The header of $(MREF std,range) for tutorials on ranges.
1014  */
1015 enum bool isForwardRange(R) = isInputRange!R
1016     && is(typeof((R r) { return r.save; } (R.init)) == R);
1017 
1018 ///
1019 @safe unittest
1020 {
1021     static assert(!isForwardRange!(int));
1022     static assert( isForwardRange!(int[]));
1023     static assert( isForwardRange!(inout(int)[]));
1024 }
1025 
1026 @safe unittest
1027 {
1028     // BUG 14544
1029     struct R14544
1030     {
1031         int front() { return 0;}
1032         void popFront() {}
1033         bool empty() { return false; }
1034         R14544 save() {return this;}
1035     }
1036 
1037     static assert( isForwardRange!R14544 );
1038 }
1039 
1040 /**
1041 Returns `true` if `R` is a bidirectional range. A bidirectional
1042 range is a forward range that also offers the primitives `back` and
1043 `popBack`. The following code should compile for any bidirectional
1044 range.
1045 
1046 The semantics of a bidirectional range (not checkable during
1047 compilation) are assumed to be the following (`r` is an object of
1048 type `R`):
1049 
1050 $(UL $(LI `r.back` returns (possibly a reference to) the last
1051 element in the range. Calling `r.back` is allowed only if calling
1052 `r.empty` has, or would have, returned `false`.))
1053 
1054 See_Also:
1055     The header of $(MREF std,range) for tutorials on ranges.
1056  */
1057 enum bool isBidirectionalRange(R) = isForwardRange!R
1058     && is(typeof((R r) => r.popBack))
1059     && (is(typeof((return ref R r) => r.back)) || is(typeof(ref (return ref R r) => r.back)))
1060     && is(typeof(R.init.back.init) == ElementType!R);
1061 
1062 ///
1063 @safe unittest
1064 {
1065     alias R = int[];
1066     R r = [0,1];
1067     static assert(isForwardRange!R);           // is forward range
1068     r.popBack();                               // can invoke popBack
1069     auto t = r.back;                           // can get the back of the range
1070     auto w = r.front;
1071     static assert(is(typeof(t) == typeof(w))); // same type for front and back
1072 }
1073 
1074 @safe unittest
1075 {
1076     struct A {}
1077     struct B
1078     {
1079         void popFront();
1080         @property bool empty();
1081         @property int front();
1082     }
1083     struct C
1084     {
1085         @property bool empty();
1086         @property C save();
1087         void popFront();
1088         @property int front();
1089         void popBack();
1090         @property int back();
1091     }
1092     static assert(!isBidirectionalRange!(A));
1093     static assert(!isBidirectionalRange!(B));
1094     static assert( isBidirectionalRange!(C));
1095     static assert( isBidirectionalRange!(int[]));
1096     static assert( isBidirectionalRange!(char[]));
1097     static assert( isBidirectionalRange!(inout(int)[]));
1098 }
1099 
1100 /**
1101 Returns `true` if `R` is a random-access range. A random-access
1102 range is a bidirectional range that also offers the primitive $(D
1103 opIndex), OR an infinite forward range that offers `opIndex`. In
1104 either case, the range must either offer `length` or be
1105 infinite. The following code should compile for any random-access
1106 range.
1107 
1108 The semantics of a random-access range (not checkable during
1109 compilation) are assumed to be the following (`r` is an object of
1110 type `R`): $(UL $(LI `r.opIndex(n)` returns a reference to the
1111 `n`th element in the range.))
1112 
1113 Although `char[]` and `wchar[]` (as well as their qualified
1114 versions including `string` and `wstring`) are arrays, $(D
1115 isRandomAccessRange) yields `false` for them because they use
1116 variable-length encodings (UTF-8 and UTF-16 respectively). These types
1117 are bidirectional ranges only.
1118 
1119 See_Also:
1120     The header of $(MREF std,range) for tutorials on ranges.
1121  */
1122 enum bool isRandomAccessRange(R) =
1123     is(typeof(lvalueOf!R[1]) == ElementType!R)
1124     && !(isAutodecodableString!R && !isAggregateType!R)
1125     && isForwardRange!R
1126     && (isBidirectionalRange!R || isInfinite!R)
1127     && (hasLength!R || isInfinite!R)
1128     && (isInfinite!R || !is(typeof(lvalueOf!R[$ - 1]))
1129         || is(typeof(lvalueOf!R[$ - 1]) == ElementType!R));
1130 
1131 ///
1132 @safe unittest
1133 {
1134     import std.traits : isAggregateType, isAutodecodableString;
1135 
1136     alias R = int[];
1137 
1138     // range is finite and bidirectional or infinite and forward.
1139     static assert(isBidirectionalRange!R ||
1140                   isForwardRange!R && isInfinite!R);
1141 
1142     R r = [0,1];
1143     auto e = r[1]; // can index
1144     auto f = r.front;
1145     static assert(is(typeof(e) == typeof(f))); // same type for indexed and front
1146     static assert(!(isAutodecodableString!R && !isAggregateType!R)); // narrow strings cannot be indexed as ranges
1147     static assert(hasLength!R || isInfinite!R); // must have length or be infinite
1148 
1149     // $ must work as it does with arrays if opIndex works with $
1150     static if (is(typeof(r[$])))
1151     {
1152         static assert(is(typeof(f) == typeof(r[$])));
1153 
1154         // $ - 1 doesn't make sense with infinite ranges but needs to work
1155         // with finite ones.
1156         static if (!isInfinite!R)
1157             static assert(is(typeof(f) == typeof(r[$ - 1])));
1158     }
1159 }
1160 
1161 @safe unittest
1162 {
1163     struct A {}
1164     struct B
1165     {
1166         void popFront();
1167         @property bool empty();
1168         @property int front();
1169     }
1170     struct C
1171     {
1172         void popFront();
1173         @property bool empty();
1174         @property int front();
1175         void popBack();
1176         @property int back();
1177     }
1178     struct D
1179     {
1180         @property bool empty();
1181         @property D save();
1182         @property int front();
1183         void popFront();
1184         @property int back();
1185         void popBack();
1186         ref int opIndex(uint);
1187         @property size_t length();
1188         alias opDollar = length;
1189         //int opSlice(uint, uint);
1190     }
1191     struct E
1192     {
1193         bool empty();
1194         E save();
1195         int front();
1196         void popFront();
1197         int back();
1198         void popBack();
1199         ref int opIndex(uint);
1200         size_t length();
1201         alias opDollar = length;
1202         //int opSlice(uint, uint);
1203     }
1204     static assert(!isRandomAccessRange!(A));
1205     static assert(!isRandomAccessRange!(B));
1206     static assert(!isRandomAccessRange!(C));
1207     static assert( isRandomAccessRange!(D));
1208     static assert( isRandomAccessRange!(E));
1209     static assert( isRandomAccessRange!(int[]));
1210     static assert( isRandomAccessRange!(inout(int)[]));
1211 }
1212 
1213 @safe unittest
1214 {
1215     // Test fix for bug 6935.
1216     struct R
1217     {
1218         @disable this();
1219 
1220         @property bool empty() const { return false; }
1221         @property int front() const { return 0; }
1222         void popFront() {}
1223 
1224         @property R save() { return this; }
1225 
1226         @property int back() const { return 0; }
1227         void popBack(){}
1228 
1229         int opIndex(size_t n) const { return 0; }
1230         @property size_t length() const { return 0; }
1231         alias opDollar = length;
1232 
1233         void put(int e){  }
1234     }
1235     static assert(isInputRange!R);
1236     static assert(isForwardRange!R);
1237     static assert(isBidirectionalRange!R);
1238     static assert(isRandomAccessRange!R);
1239     static assert(isOutputRange!(R, int));
1240 }
1241 
1242 /**
1243 Returns `true` iff `R` is an input range that supports the
1244 `moveFront` primitive, as well as `moveBack` and `moveAt` if it's a
1245 bidirectional or random access range. These may be explicitly implemented, or
1246 may work via the default behavior of the module level functions `moveFront`
1247 and friends. The following code should compile for any range
1248 with mobile elements.
1249 
1250 ----
1251 alias E = ElementType!R;
1252 R r;
1253 static assert(isInputRange!R);
1254 static assert(is(typeof(moveFront(r)) == E));
1255 static if (isBidirectionalRange!R)
1256     static assert(is(typeof(moveBack(r)) == E));
1257 static if (isRandomAccessRange!R)
1258     static assert(is(typeof(moveAt(r, 0)) == E));
1259 ----
1260  */
1261 enum bool hasMobileElements(R) =
1262     isInputRange!R
1263     && is(typeof(moveFront(lvalueOf!R)) == ElementType!R)
1264     && (!isBidirectionalRange!R
1265         || is(typeof(moveBack(lvalueOf!R)) == ElementType!R))
1266     && (!isRandomAccessRange!R
1267         || is(typeof(moveAt(lvalueOf!R, 0)) == ElementType!R));
1268 
1269 ///
1270 @safe unittest
1271 {
1272     import std.algorithm.iteration : map;
1273     import std.range : iota, repeat;
1274 
1275     static struct HasPostblit
1276     {
1277         this(this) {}
1278     }
1279 
1280     auto nonMobile = map!"a"(repeat(HasPostblit.init));
1281     static assert(!hasMobileElements!(typeof(nonMobile)));
1282     static assert( hasMobileElements!(int[]));
1283     static assert( hasMobileElements!(inout(int)[]));
1284     static assert( hasMobileElements!(typeof(iota(1000))));
1285 
1286     static assert( hasMobileElements!( string));
1287     static assert( hasMobileElements!(dstring));
1288     static assert( hasMobileElements!( char[]));
1289     static assert( hasMobileElements!(dchar[]));
1290 }
1291 
1292 /**
1293 The element type of `R`. `R` does not have to be a range. The
1294 element type is determined as the type yielded by `r.front` for an
1295 object `r` of type `R`. For example, `ElementType!(T[])` is
1296 `T` if `T[]` isn't a narrow string; if it is, the element type is
1297 `dchar`. If `R` doesn't have `front`, `ElementType!R` is
1298 `void`.
1299  */
1300 template ElementType(R)
1301 {
1302     static if (is(typeof(R.init.front.init) T))
1303         alias ElementType = T;
1304     else
1305         alias ElementType = void;
1306 }
1307 
1308 ///
1309 @safe unittest
1310 {
1311     import std.range : iota;
1312 
1313     // Standard arrays: returns the type of the elements of the array
1314     static assert(is(ElementType!(int[]) == int));
1315 
1316     // Accessing .front retrieves the decoded dchar
1317     static assert(is(ElementType!(char[])  == dchar)); // rvalue
1318     static assert(is(ElementType!(dchar[]) == dchar)); // lvalue
1319 
1320     // Ditto
1321     static assert(is(ElementType!(string) == dchar));
1322     static assert(is(ElementType!(dstring) == immutable(dchar)));
1323 
1324     // For ranges it gets the type of .front.
1325     auto range = iota(0, 10);
1326     static assert(is(ElementType!(typeof(range)) == int));
1327 }
1328 
1329 @safe unittest
1330 {
1331     static assert(is(ElementType!(byte[]) == byte));
1332     static assert(is(ElementType!(wchar[]) == dchar)); // rvalue
1333     static assert(is(ElementType!(wstring) == dchar));
1334 }
1335 
1336 @safe unittest
1337 {
1338     enum XYZ : string { a = "foo" }
1339     auto x = XYZ.a.front;
1340     immutable char[3] a = "abc";
1341     int[] i;
1342     void[] buf;
1343     static assert(is(ElementType!(XYZ) == dchar));
1344     static assert(is(ElementType!(typeof(a)) == dchar));
1345     static assert(is(ElementType!(typeof(i)) == int));
1346     static assert(is(ElementType!(typeof(buf)) == void));
1347     static assert(is(ElementType!(inout(int)[]) == inout(int)));
1348     static assert(is(ElementType!(inout(int[])) == inout(int)));
1349 }
1350 
1351 @safe unittest
1352 {
1353     static assert(is(ElementType!(int[5]) == int));
1354     static assert(is(ElementType!(int[0]) == int));
1355     static assert(is(ElementType!(char[5]) == dchar));
1356     static assert(is(ElementType!(char[0]) == dchar));
1357 }
1358 
1359 // https://issues.dlang.org/show_bug.cgi?id=11336
1360 @safe unittest
1361 {
1362     static struct S
1363     {
1364         this(this) @disable;
1365     }
1366     static assert(is(ElementType!(S[]) == S));
1367 }
1368 
1369 // https://issues.dlang.org/show_bug.cgi?id=11401
1370 @safe unittest
1371 {
1372     // ElementType should also work for non-@propety 'front'
1373     struct E { ushort id; }
1374     struct R
1375     {
1376         E front() { return E.init; }
1377     }
1378     static assert(is(ElementType!R == E));
1379 }
1380 
1381 /**
1382 The encoding element type of `R`. For narrow strings (`char[]`,
1383 `wchar[]` and their qualified variants including `string` and
1384 `wstring`), `ElementEncodingType` is the character type of the
1385 string. For all other types, `ElementEncodingType` is the same as
1386 `ElementType`.
1387  */
1388 template ElementEncodingType(R)
1389 {
1390     static if (is(StringTypeOf!R) && is(R : E[], E))
1391         alias ElementEncodingType = E;
1392     else
1393         alias ElementEncodingType = ElementType!R;
1394 }
1395 
1396 ///
1397 @safe unittest
1398 {
1399     import std.range : iota;
1400     // internally the range stores the encoded type
1401     static assert(is(ElementEncodingType!(char[])  == char));
1402 
1403     static assert(is(ElementEncodingType!(wstring) == immutable(wchar)));
1404 
1405     static assert(is(ElementEncodingType!(byte[]) == byte));
1406 
1407     auto range = iota(0, 10);
1408     static assert(is(ElementEncodingType!(typeof(range)) == int));
1409 }
1410 
1411 @safe unittest
1412 {
1413     static assert(is(ElementEncodingType!(wchar[]) == wchar));
1414     static assert(is(ElementEncodingType!(dchar[]) == dchar));
1415     static assert(is(ElementEncodingType!(string)  == immutable(char)));
1416     static assert(is(ElementEncodingType!(dstring) == immutable(dchar)));
1417     static assert(is(ElementEncodingType!(int[])  == int));
1418 }
1419 
1420 @safe unittest
1421 {
1422     enum XYZ : string { a = "foo" }
1423     auto x = XYZ.a.front;
1424     immutable char[3] a = "abc";
1425     int[] i;
1426     void[] buf;
1427     static assert(is(ElementType!(XYZ) : dchar));
1428     static assert(is(ElementEncodingType!(char[]) == char));
1429     static assert(is(ElementEncodingType!(string) == immutable char));
1430     static assert(is(ElementType!(typeof(a)) : dchar));
1431     static assert(is(ElementType!(typeof(i)) == int));
1432     static assert(is(ElementEncodingType!(typeof(i)) == int));
1433     static assert(is(ElementType!(typeof(buf)) : void));
1434 
1435     static assert(is(ElementEncodingType!(inout char[]) : inout(char)));
1436 }
1437 
1438 @safe unittest
1439 {
1440     static assert(is(ElementEncodingType!(int[5]) == int));
1441     static assert(is(ElementEncodingType!(int[0]) == int));
1442     static assert(is(ElementEncodingType!(char[5]) == char));
1443     static assert(is(ElementEncodingType!(char[0]) == char));
1444 }
1445 
1446 /**
1447 Returns `true` if `R` is an input range and has swappable
1448 elements. The following code should compile for any range
1449 with swappable elements.
1450 
1451 ----
1452 R r;
1453 static assert(isInputRange!R);
1454 swap(r.front, r.front);
1455 static if (isBidirectionalRange!R) swap(r.back, r.front);
1456 static if (isRandomAccessRange!R) swap(r[0], r.front);
1457 ----
1458  */
1459 template hasSwappableElements(R)
1460 {
1461     import std.algorithm.mutation : swap;
1462     enum bool hasSwappableElements = isInputRange!R
1463         && is(typeof((ref R r) => swap(r.front, r.front)))
1464         && (!isBidirectionalRange!R
1465             || is(typeof((ref R r) => swap(r.back, r.front))))
1466         && (!isRandomAccessRange!R
1467             || is(typeof((ref R r) => swap(r[0], r.front))));
1468 }
1469 
1470 ///
1471 @safe unittest
1472 {
1473     static assert(!hasSwappableElements!(const int[]));
1474     static assert(!hasSwappableElements!(const(int)[]));
1475     static assert(!hasSwappableElements!(inout(int)[]));
1476     static assert( hasSwappableElements!(int[]));
1477 
1478     static assert(!hasSwappableElements!( string));
1479     static assert(!hasSwappableElements!(dstring));
1480     static assert(!hasSwappableElements!( char[]));
1481     static assert( hasSwappableElements!(dchar[]));
1482 }
1483 
1484 /**
1485 Returns `true` if `R` is an input range and has mutable
1486 elements. The following code should compile for any range
1487 with assignable elements.
1488 
1489 ----
1490 R r;
1491 static assert(isInputRange!R);
1492 r.front = r.front;
1493 static if (isBidirectionalRange!R) r.back = r.front;
1494 static if (isRandomAccessRange!R) r[0] = r.front;
1495 ----
1496  */
1497 enum bool hasAssignableElements(R) = isInputRange!R
1498     && is(typeof(lvalueOf!R.front = lvalueOf!R.front))
1499     && (!isBidirectionalRange!R
1500         || is(typeof(lvalueOf!R.back = lvalueOf!R.back)))
1501     && (!isRandomAccessRange!R
1502         || is(typeof(lvalueOf!R[0] = lvalueOf!R.front)));
1503 
1504 ///
1505 @safe unittest
1506 {
1507     static assert(!hasAssignableElements!(const int[]));
1508     static assert(!hasAssignableElements!(const(int)[]));
1509     static assert( hasAssignableElements!(int[]));
1510     static assert(!hasAssignableElements!(inout(int)[]));
1511 
1512     static assert(!hasAssignableElements!( string));
1513     static assert(!hasAssignableElements!(dstring));
1514     static assert(!hasAssignableElements!( char[]));
1515     static assert( hasAssignableElements!(dchar[]));
1516 }
1517 
1518 /**
1519 Tests whether the range `R` has lvalue elements. These are defined as
1520 elements that can be passed by reference and have their address taken.
1521 The following code should compile for any range with lvalue elements.
1522 ----
1523 void passByRef(ref ElementType!R stuff);
1524 ...
1525 static assert(isInputRange!R);
1526 passByRef(r.front);
1527 static if (isBidirectionalRange!R) passByRef(r.back);
1528 static if (isRandomAccessRange!R) passByRef(r[0]);
1529 ----
1530 */
1531 enum bool hasLvalueElements(R) = isInputRange!R
1532     && is(typeof(isLvalue(lvalueOf!R.front)))
1533     && (!isBidirectionalRange!R
1534         || is(typeof(isLvalue(lvalueOf!R.back))))
1535     && (!isRandomAccessRange!R
1536         || is(typeof(isLvalue(lvalueOf!R[0]))));
1537 
1538 /* Compile successfully if argument of type T is an lvalue
1539  */
1540 private void isLvalue(T)(T)
1541 if (0);
1542 
1543 private void isLvalue(T)(ref T)
1544 if (1);
1545 
1546 ///
1547 @safe unittest
1548 {
1549     import std.range : iota, chain;
1550 
1551     static assert( hasLvalueElements!(int[]));
1552     static assert( hasLvalueElements!(const(int)[]));
1553     static assert( hasLvalueElements!(inout(int)[]));
1554     static assert( hasLvalueElements!(immutable(int)[]));
1555     static assert(!hasLvalueElements!(typeof(iota(3))));
1556 
1557     static assert(!hasLvalueElements!( string));
1558     static assert( hasLvalueElements!(dstring));
1559     static assert(!hasLvalueElements!( char[]));
1560     static assert( hasLvalueElements!(dchar[]));
1561 
1562     auto c = chain([1, 2, 3], [4, 5, 6]);
1563     static assert( hasLvalueElements!(typeof(c)));
1564 }
1565 
1566 @safe unittest
1567 {
1568     // bugfix 6336
1569     struct S { immutable int value; }
1570     static assert( isInputRange!(S[]));
1571     static assert( hasLvalueElements!(S[]));
1572 }
1573 
1574 /**
1575 Yields `true` if `R` has a `length` member that returns a value of `size_t`
1576 type. `R` does not have to be a range. If `R` is a range, algorithms in the
1577 standard library are only guaranteed to support `length` with type `size_t`.
1578 
1579 Note that `length` is an optional primitive as no range must implement it. Some
1580 ranges do not store their length explicitly, some cannot compute it without
1581 actually exhausting the range (e.g. socket streams), and some other ranges may
1582 be infinite.
1583 
1584 Although narrow string types (`char[]`, `wchar[]`, and their qualified
1585 derivatives) do define a `length` property, `hasLength` yields `false` for them.
1586 This is because a narrow string's length does not reflect the number of
1587 characters, but instead the number of encoding units, and as such is not useful
1588 with range-oriented algorithms. To use strings as random-access ranges with
1589 length, use $(REF representation, std, string) or $(REF byCodeUnit, std, utf).
1590 */
1591 template hasLength(R)
1592 {
1593     static if (is(typeof(((R* r) => r.length)(null)) Length))
1594         enum bool hasLength = is(Length == size_t) &&
1595                               !(isAutodecodableString!R && !isAggregateType!R);
1596     else
1597         enum bool hasLength = false;
1598 }
1599 
1600 ///
1601 @safe unittest
1602 {
1603     static assert(!hasLength!(char[]));
1604     static assert( hasLength!(int[]));
1605     static assert( hasLength!(inout(int)[]));
1606 
1607     struct A { size_t length() { return 0; } }
1608     struct B { @property size_t length() { return 0; } }
1609     static assert( hasLength!(A));
1610     static assert( hasLength!(B));
1611 }
1612 
1613 // test combinations which are invalid on some platforms
1614 @safe unittest
1615 {
1616     struct A { ulong length; }
1617     struct B { @property uint length() { return 0; } }
1618 
1619     static if (is(size_t == uint))
1620     {
1621         static assert(!hasLength!(A));
1622         static assert(hasLength!(B));
1623     }
1624     else static if (is(size_t == ulong))
1625     {
1626         static assert(hasLength!(A));
1627         static assert(!hasLength!(B));
1628     }
1629 }
1630 
1631 // test combinations which are invalid on all platforms
1632 @safe unittest
1633 {
1634     struct A { long length; }
1635     struct B { int length; }
1636     struct C { ubyte length; }
1637     struct D { char length; }
1638     static assert(!hasLength!(A));
1639     static assert(!hasLength!(B));
1640     static assert(!hasLength!(C));
1641     static assert(!hasLength!(D));
1642 }
1643 
1644 /**
1645 Returns `true` if `R` is an infinite input range. An
1646 infinite input range is an input range that has a statically-defined
1647 enumerated member called `empty` that is always `false`,
1648 for example:
1649 
1650 ----
1651 struct MyInfiniteRange
1652 {
1653     enum bool empty = false;
1654     ...
1655 }
1656 ----
1657  */
1658 
1659 template isInfinite(R)
1660 {
1661     static if (isInputRange!R && __traits(compiles, { enum e = R.empty; }))
1662         enum bool isInfinite = !R.empty;
1663     else
1664         enum bool isInfinite = false;
1665 }
1666 
1667 ///
1668 @safe unittest
1669 {
1670     import std.range : Repeat;
1671     static assert(!isInfinite!(int[]));
1672     static assert( isInfinite!(Repeat!(int)));
1673 }
1674 
1675 /**
1676 Returns `true` if `R` offers a slicing operator with integral boundaries
1677 that returns a forward range type.
1678 
1679 For finite ranges, the result of `opSlice` must be of the same type as the
1680 original range type. If the range defines `opDollar`, then it must support
1681 subtraction.
1682 
1683 For infinite ranges, when $(I not) using `opDollar`, the result of
1684 `opSlice` must be the result of $(LREF take) or $(LREF takeExactly) on the
1685 original range (they both return the same type for infinite ranges). However,
1686 when using `opDollar`, the result of `opSlice` must be that of the
1687 original range type.
1688 
1689 The following expression must be true for `hasSlicing` to be `true`:
1690 
1691 ----
1692     isForwardRange!R
1693     && !(isAutodecodableString!R && !isAggregateType!R)
1694     && is(typeof((R r) { return r[1 .. 1].length; } (R.init)) == size_t)
1695     && (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R)
1696     && (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R))
1697     && (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R
1698         || is(typeof(lvalueOf!R[0 .. $ - 1]) == R))
1699     && is(typeof((ref R r)
1700     {
1701         static assert(isForwardRange!(typeof(r[1 .. 2])));
1702     }));
1703 ----
1704  */
1705 enum bool hasSlicing(R) = isForwardRange!R
1706     && !(isAutodecodableString!R && !isAggregateType!R)
1707     && is(typeof((R r) { return r[1 .. 1].length; } (R.init)) == size_t)
1708     && (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R)
1709     && (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R))
1710     && (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R
1711         || is(typeof(lvalueOf!R[0 .. $ - 1]) == R))
1712     && is(typeof((ref R r)
1713     {
1714         static assert(isForwardRange!(typeof(r[1 .. 2])));
1715     }));
1716 
1717 ///
1718 @safe unittest
1719 {
1720     import std.range : takeExactly;
1721     static assert( hasSlicing!(int[]));
1722     static assert( hasSlicing!(const(int)[]));
1723     static assert(!hasSlicing!(const int[]));
1724     static assert( hasSlicing!(inout(int)[]));
1725     static assert(!hasSlicing!(inout int []));
1726     static assert( hasSlicing!(immutable(int)[]));
1727     static assert(!hasSlicing!(immutable int[]));
1728     static assert(!hasSlicing!string);
1729     static assert( hasSlicing!dstring);
1730 
1731     enum rangeFuncs = "@property int front();" ~
1732                       "void popFront();" ~
1733                       "@property bool empty();" ~
1734                       "@property auto save() { return this; }" ~
1735                       "@property size_t length();";
1736 
1737     struct A { mixin(rangeFuncs); int opSlice(size_t, size_t); }
1738     struct B { mixin(rangeFuncs); B opSlice(size_t, size_t); }
1739     struct C { mixin(rangeFuncs); @disable this(); C opSlice(size_t, size_t); }
1740     struct D { mixin(rangeFuncs); int[] opSlice(size_t, size_t); }
1741     static assert(!hasSlicing!(A));
1742     static assert( hasSlicing!(B));
1743     static assert( hasSlicing!(C));
1744     static assert(!hasSlicing!(D));
1745 
1746     struct InfOnes
1747     {
1748         enum empty = false;
1749         void popFront() {}
1750         @property int front() { return 1; }
1751         @property InfOnes save() { return this; }
1752         auto opSlice(size_t i, size_t j) { return takeExactly(this, j - i); }
1753         auto opSlice(size_t i, Dollar d) { return this; }
1754 
1755         struct Dollar {}
1756         Dollar opDollar() const { return Dollar.init; }
1757     }
1758 
1759     static assert(hasSlicing!InfOnes);
1760 }
1761 
1762 /**
1763 This is a best-effort implementation of `length` for any kind of
1764 range.
1765 
1766 If `hasLength!Range`, simply returns `range.length` without
1767 checking `upTo` (when specified).
1768 
1769 Otherwise, walks the range through its length and returns the number
1770 of elements seen. Performes $(BIGOH n) evaluations of `range.empty`
1771 and `range.popFront()`, where `n` is the effective length of $(D
1772 range).
1773 
1774 The `upTo` parameter is useful to "cut the losses" in case
1775 the interest is in seeing whether the range has at least some number
1776 of elements. If the parameter `upTo` is specified, stops if $(D
1777 upTo) steps have been taken and returns `upTo`.
1778 
1779 Infinite ranges are compatible, provided the parameter `upTo` is
1780 specified, in which case the implementation simply returns upTo.
1781  */
1782 auto walkLength(Range)(Range range)
1783 if (isInputRange!Range && !isInfinite!Range)
1784 {
1785     static if (hasLength!Range)
1786         return range.length;
1787     else
1788     {
1789         size_t result;
1790         static if (autodecodeStrings && isNarrowString!Range)
1791         {
1792             import std.utf : codeUnitLimit;
1793             result = range.length;
1794             foreach (const i, const c; range)
1795             {
1796                 if (c >= codeUnitLimit!Range)
1797                 {
1798                     result = i;
1799                     break;
1800                 }
1801             }
1802             range = range[result .. $];
1803         }
1804         for ( ; !range.empty ; range.popFront() )
1805             ++result;
1806         return result;
1807     }
1808 }
1809 /// ditto
1810 auto walkLength(Range)(Range range, const size_t upTo)
1811 if (isInputRange!Range)
1812 {
1813     static if (hasLength!Range)
1814         return range.length;
1815     else static if (isInfinite!Range)
1816         return upTo;
1817     else
1818     {
1819         size_t result;
1820         static if (autodecodeStrings && isNarrowString!Range)
1821         {
1822             import std.utf : codeUnitLimit;
1823             result = upTo > range.length ? range.length : upTo;
1824             foreach (const i, const c; range[0 .. result])
1825             {
1826                 if (c >= codeUnitLimit!Range)
1827                 {
1828                     result = i;
1829                     break;
1830                 }
1831             }
1832             range = range[result .. $];
1833         }
1834         for ( ; result < upTo && !range.empty ; range.popFront() )
1835             ++result;
1836         return result;
1837     }
1838 }
1839 
1840 ///
1841 @safe unittest
1842 {
1843     import std.range : iota;
1844 
1845     assert(10.iota.walkLength == 10);
1846     // iota has a length function, and therefore the
1847     // doesn't have to be walked, and the upTo
1848     // parameter is ignored
1849     assert(10.iota.walkLength(5) == 10);
1850 }
1851 
1852 @safe unittest
1853 {
1854     import std.algorithm.iteration : filter;
1855     import std.range : recurrence, take;
1856 
1857     //hasLength Range
1858     int[] a = [ 1, 2, 3 ];
1859     assert(walkLength(a) == 3);
1860     assert(walkLength(a, 0) == 3);
1861     assert(walkLength(a, 2) == 3);
1862     assert(walkLength(a, 4) == 3);
1863 
1864     //Forward Range
1865     auto b = filter!"true"([1, 2, 3, 4]);
1866     assert(b.walkLength() == 4);
1867     assert(b.walkLength(0) == 0);
1868     assert(b.walkLength(2) == 2);
1869     assert(b.walkLength(4) == 4);
1870     assert(b.walkLength(6) == 4);
1871 
1872     //Infinite Range
1873     auto fibs = recurrence!"a[n-1] + a[n-2]"(1, 1);
1874     assert(!__traits(compiles, fibs.walkLength()));
1875     assert(fibs.take(10).walkLength() == 10);
1876     assert(fibs.walkLength(55) == 55);
1877 }
1878 
1879 /**
1880     `popFrontN` eagerly advances `r` itself (not a copy) up to `n` times
1881     (by calling `r.popFront`). `popFrontN` takes `r` by `ref`,
1882     so it mutates the original range. Completes in $(BIGOH 1) steps for ranges
1883     that support slicing and have length.
1884     Completes in $(BIGOH n) time for all other ranges.
1885 
1886     `popBackN` behaves the same as `popFrontN` but instead removes
1887     elements from the back of the (bidirectional) range instead of the front.
1888 
1889     Returns:
1890     How much `r` was actually advanced, which may be less than `n` if
1891     `r` did not have at least `n` elements.
1892 
1893     See_Also: $(REF drop, std, range), $(REF dropBack, std, range)
1894 */
1895 size_t popFrontN(Range)(ref Range r, size_t n)
1896 if (isInputRange!Range)
1897 {
1898     static if (hasLength!Range)
1899     {
1900         n = cast(size_t) (n < r.length ? n : r.length);
1901     }
1902 
1903     static if (hasSlicing!Range && is(typeof(r = r[n .. $])))
1904     {
1905         r = r[n .. $];
1906     }
1907     else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar.
1908     {
1909         r = r[n .. r.length];
1910     }
1911     else
1912     {
1913         static if (hasLength!Range)
1914         {
1915             foreach (i; 0 .. n)
1916                 r.popFront();
1917         }
1918         else
1919         {
1920             foreach (i; 0 .. n)
1921             {
1922                 if (r.empty) return i;
1923                 r.popFront();
1924             }
1925         }
1926     }
1927     return n;
1928 }
1929 
1930 /// ditto
1931 size_t popBackN(Range)(ref Range r, size_t n)
1932 if (isBidirectionalRange!Range)
1933 {
1934     static if (hasLength!Range)
1935     {
1936         n = cast(size_t) (n < r.length ? n : r.length);
1937     }
1938 
1939     static if (hasSlicing!Range && is(typeof(r = r[0 .. $ - n])))
1940     {
1941         r = r[0 .. $ - n];
1942     }
1943     else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar.
1944     {
1945         r = r[0 .. r.length - n];
1946     }
1947     else
1948     {
1949         static if (hasLength!Range)
1950         {
1951             foreach (i; 0 .. n)
1952                 r.popBack();
1953         }
1954         else
1955         {
1956             foreach (i; 0 .. n)
1957             {
1958                 if (r.empty) return i;
1959                 r.popBack();
1960             }
1961         }
1962     }
1963     return n;
1964 }
1965 
1966 ///
1967 @safe unittest
1968 {
1969     int[] a = [ 1, 2, 3, 4, 5 ];
1970     a.popFrontN(2);
1971     assert(a == [ 3, 4, 5 ]);
1972     a.popFrontN(7);
1973     assert(a == [ ]);
1974 }
1975 
1976 ///
1977 @safe unittest
1978 {
1979     import std.algorithm.comparison : equal;
1980     import std.range : iota;
1981     auto LL = iota(1L, 7L);
1982     auto r = popFrontN(LL, 2);
1983     assert(equal(LL, [3L, 4L, 5L, 6L]));
1984     assert(r == 2);
1985 }
1986 
1987 ///
1988 @safe unittest
1989 {
1990     int[] a = [ 1, 2, 3, 4, 5 ];
1991     a.popBackN(2);
1992     assert(a == [ 1, 2, 3 ]);
1993     a.popBackN(7);
1994     assert(a == [ ]);
1995 }
1996 
1997 ///
1998 @safe unittest
1999 {
2000     import std.algorithm.comparison : equal;
2001     import std.range : iota;
2002     auto LL = iota(1L, 7L);
2003     auto r = popBackN(LL, 2);
2004     assert(equal(LL, [1L, 2L, 3L, 4L]));
2005     assert(r == 2);
2006 }
2007 
2008 /**
2009     Eagerly advances `r` itself (not a copy) exactly `n` times (by
2010     calling `r.popFront`). `popFrontExactly` takes `r` by `ref`,
2011     so it mutates the original range. Completes in $(BIGOH 1) steps for ranges
2012     that support slicing, and have either length or are infinite.
2013     Completes in $(BIGOH n) time for all other ranges.
2014 
2015     Note: Unlike $(LREF popFrontN), `popFrontExactly` will assume that the
2016     range holds at least `n` elements. This makes `popFrontExactly`
2017     faster than `popFrontN`, but it also means that if `range` does
2018     not contain at least `n` elements, it will attempt to call `popFront`
2019     on an empty range, which is undefined behavior. So, only use
2020     `popFrontExactly` when it is guaranteed that `range` holds at least
2021     `n` elements.
2022 
2023     `popBackExactly` will behave the same but instead removes elements from
2024     the back of the (bidirectional) range instead of the front.
2025 
2026     See_Also: $(REF dropExactly, std, range), $(REF dropBackExactly, std, range)
2027 */
2028 void popFrontExactly(Range)(ref Range r, size_t n)
2029 if (isInputRange!Range)
2030 {
2031     static if (hasLength!Range)
2032         assert(n <= r.length, "range is smaller than amount of items to pop");
2033 
2034     static if (hasSlicing!Range && is(typeof(r = r[n .. $])))
2035         r = r[n .. $];
2036     else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar.
2037         r = r[n .. r.length];
2038     else
2039         foreach (i; 0 .. n)
2040             r.popFront();
2041 }
2042 
2043 /// ditto
2044 void popBackExactly(Range)(ref Range r, size_t n)
2045 if (isBidirectionalRange!Range)
2046 {
2047     static if (hasLength!Range)
2048         assert(n <= r.length, "range is smaller than amount of items to pop");
2049 
2050     static if (hasSlicing!Range && is(typeof(r = r[0 .. $ - n])))
2051         r = r[0 .. $ - n];
2052     else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar.
2053         r = r[0 .. r.length - n];
2054     else
2055         foreach (i; 0 .. n)
2056             r.popBack();
2057 }
2058 
2059 ///
2060 @safe unittest
2061 {
2062     import std.algorithm.comparison : equal;
2063     import std.algorithm.iteration : filterBidirectional;
2064 
2065     auto a = [1, 2, 3];
2066     a.popFrontExactly(1);
2067     assert(a == [2, 3]);
2068     a.popBackExactly(1);
2069     assert(a == [2]);
2070 
2071     string s = "日本語";
2072     s.popFrontExactly(1);
2073     assert(s == "本語");
2074     s.popBackExactly(1);
2075     assert(s == "本");
2076 
2077     auto bd = filterBidirectional!"true"([1, 2, 3]);
2078     bd.popFrontExactly(1);
2079     assert(bd.equal([2, 3]));
2080     bd.popBackExactly(1);
2081     assert(bd.equal([2]));
2082 }
2083 
2084 /**
2085    Moves the front of `r` out and returns it.
2086 
2087    If `r.front` is a struct with a destructor or copy constructor defined, it
2088    is reset to its `.init` value after its value is moved. Otherwise, it is
2089    left unchanged.
2090 
2091    In either case, `r.front` is left in a destroyable state that does not
2092    allocate any resources.
2093 */
2094 ElementType!R moveFront(R)(R r)
2095 {
2096     static if (is(typeof(&r.moveFront)))
2097     {
2098         return r.moveFront();
2099     }
2100     else static if (!hasElaborateCopyConstructor!(ElementType!R))
2101     {
2102         return r.front;
2103     }
2104     else static if (is(typeof(&(r.front())) == ElementType!R*))
2105     {
2106         import std.algorithm.mutation : move;
2107         return move(r.front);
2108     }
2109     else
2110     {
2111         static assert(0,
2112                 "Cannot move front of a range with a postblit and an rvalue front.");
2113     }
2114 }
2115 
2116 ///
2117 @safe unittest
2118 {
2119     auto a = [ 1, 2, 3 ];
2120     assert(moveFront(a) == 1);
2121     assert(a.length == 3);
2122 
2123     // define a perfunctory input range
2124     struct InputRange
2125     {
2126         enum bool empty = false;
2127         enum int front = 7;
2128         void popFront() {}
2129         int moveFront() { return 43; }
2130     }
2131     InputRange r;
2132     // calls r.moveFront
2133     assert(moveFront(r) == 43);
2134 }
2135 
2136 @safe unittest
2137 {
2138     struct R
2139     {
2140         @property ref int front() { static int x = 42; return x; }
2141         this(this){}
2142     }
2143     R r;
2144     assert(moveFront(r) == 42);
2145 }
2146 
2147 /**
2148    Moves the back of `r` out and returns it. Leaves `r.back` in a
2149    destroyable state that does not allocate any resources (usually equal
2150    to its `.init` value).
2151 */
2152 ElementType!R moveBack(R)(R r)
2153 {
2154     static if (is(typeof(&r.moveBack)))
2155     {
2156         return r.moveBack();
2157     }
2158     else static if (!hasElaborateCopyConstructor!(ElementType!R))
2159     {
2160         return r.back;
2161     }
2162     else static if (is(typeof(&(r.back())) == ElementType!R*))
2163     {
2164         import std.algorithm.mutation : move;
2165         return move(r.back);
2166     }
2167     else
2168     {
2169         static assert(0,
2170                 "Cannot move back of a range with a postblit and an rvalue back.");
2171     }
2172 }
2173 
2174 ///
2175 @safe unittest
2176 {
2177     struct TestRange
2178     {
2179         int payload = 5;
2180         @property bool empty() { return false; }
2181         @property TestRange save() { return this; }
2182         @property ref int front() return { return payload; }
2183         @property ref int back() return { return payload; }
2184         void popFront() { }
2185         void popBack() { }
2186     }
2187     static assert(isBidirectionalRange!TestRange);
2188     TestRange r;
2189     auto x = moveBack(r);
2190     assert(x == 5);
2191 }
2192 
2193 /**
2194    Moves element at index `i` of `r` out and returns it. Leaves $(D
2195    r[i]) in a destroyable state that does not allocate any resources
2196    (usually equal to its `.init` value).
2197 */
2198 ElementType!R moveAt(R)(R r, size_t i)
2199 {
2200     static if (is(typeof(&r.moveAt)))
2201     {
2202         return r.moveAt(i);
2203     }
2204     else static if (!hasElaborateCopyConstructor!(ElementType!(R)))
2205     {
2206         return r[i];
2207     }
2208     else static if (is(typeof(&r[i]) == ElementType!R*))
2209     {
2210         import std.algorithm.mutation : move;
2211         return move(r[i]);
2212     }
2213     else
2214     {
2215         static assert(0,
2216                 "Cannot move element of a range with a postblit and rvalue elements.");
2217     }
2218 }
2219 
2220 ///
2221 @safe unittest
2222 {
2223     auto a = [1,2,3,4];
2224     foreach (idx, it; a)
2225     {
2226         assert(it == moveAt(a, idx));
2227     }
2228 }
2229 
2230 @safe unittest
2231 {
2232     import std.internal.test.dummyrange;
2233 
2234     foreach (DummyType; AllDummyRanges)
2235     {
2236         auto d = DummyType.init;
2237         assert(moveFront(d) == 1);
2238 
2239         static if (isBidirectionalRange!DummyType)
2240         {
2241             assert(moveBack(d) == 10);
2242         }
2243 
2244         static if (isRandomAccessRange!DummyType)
2245         {
2246             assert(moveAt(d, 2) == 3);
2247         }
2248     }
2249 }
2250 
2251 /**
2252 Implements the range interface primitive `empty` for types that
2253 obey $(LREF hasLength) property and for narrow strings. Due to the
2254 fact that nonmember functions can be called with the first argument
2255 using the dot notation, `a.empty` is equivalent to `empty(a)`.
2256  */
2257 @property bool empty(T)(auto ref scope T a)
2258 if (is(typeof(a.length) : size_t))
2259 {
2260     return !a.length;
2261 }
2262 
2263 ///
2264 @safe pure nothrow unittest
2265 {
2266     auto a = [ 1, 2, 3 ];
2267     assert(!a.empty);
2268     assert(a[3 .. $].empty);
2269 
2270     int[string] b;
2271     assert(b.empty);
2272     b["zero"] = 0;
2273     assert(!b.empty);
2274 }
2275 
2276 /**
2277 Implements the range interface primitive `save` for built-in
2278 arrays. Due to the fact that nonmember functions can be called with
2279 the first argument using the dot notation, `array.save` is
2280 equivalent to `save(array)`. The function does not duplicate the
2281 content of the array, it simply returns its argument.
2282  */
2283 @property inout(T)[] save(T)(return scope inout(T)[] a) @safe pure nothrow @nogc
2284 {
2285     return a;
2286 }
2287 
2288 ///
2289 @safe pure nothrow unittest
2290 {
2291     auto a = [ 1, 2, 3 ];
2292     auto b = a.save;
2293     assert(b is a);
2294 }
2295 
2296 /**
2297 Implements the range interface primitive `popFront` for built-in
2298 arrays. Due to the fact that nonmember functions can be called with
2299 the first argument using the dot notation, `array.popFront` is
2300 equivalent to `popFront(array)`. For $(GLOSSARY narrow strings),
2301 `popFront` automatically advances to the next $(GLOSSARY code
2302 point).
2303 */
2304 void popFront(T)(scope ref inout(T)[] a) @safe pure nothrow @nogc
2305 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2306 {
2307     assert(a.length, "Attempting to popFront() past the end of an array of " ~ T.stringof);
2308     a = a[1 .. $];
2309 }
2310 
2311 ///
2312 @safe pure nothrow unittest
2313 {
2314     auto a = [ 1, 2, 3 ];
2315     a.popFront();
2316     assert(a == [ 2, 3 ]);
2317 }
2318 
2319 @safe unittest
2320 {
2321     static assert(!is(typeof({          int[4] a; popFront(a); })));
2322     static assert(!is(typeof({ immutable int[] a; popFront(a); })));
2323     static assert(!is(typeof({          void[] a; popFront(a); })));
2324 }
2325 
2326 /// ditto
2327 void popFront(C)(scope ref inout(C)[] str) @trusted pure nothrow
2328 if (isAutodecodableString!(C[]))
2329 {
2330     import std.algorithm.comparison : min;
2331 
2332     assert(str.length, "Attempting to popFront() past the end of an array of " ~ C.stringof);
2333 
2334     static if (is(immutable C == immutable char))
2335     {
2336         static immutable ubyte[] charWidthTab = [
2337             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2338             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2339             3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2340             4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
2341         ];
2342 
2343         immutable c = str[0];
2344         immutable charWidth = c < 192 ? 1 : charWidthTab.ptr[c - 192];
2345         str = str.ptr[min(str.length, charWidth) .. str.length];
2346     }
2347     else static if (is(immutable C == immutable wchar))
2348     {
2349         immutable u = str[0];
2350         immutable seqLen = 1 + (u >= 0xD800 && u <= 0xDBFF);
2351         str = str.ptr[min(seqLen, str.length) .. str.length];
2352     }
2353     else static assert(0, "Bad template constraint.");
2354 }
2355 
2356 @safe pure unittest
2357 {
2358     import std.meta : AliasSeq;
2359 
2360     static foreach (S; AliasSeq!(string, wstring, dstring))
2361     {{
2362         S s = "\xC2\xA9hello";
2363         s.popFront();
2364         assert(s == "hello");
2365 
2366         S str = "hello\U00010143\u0100\U00010143";
2367         foreach (dchar c; ['h', 'e', 'l', 'l', 'o', '\U00010143', '\u0100', '\U00010143'])
2368         {
2369             assert(str.front == c);
2370             str.popFront();
2371         }
2372         assert(str.empty);
2373 
2374         static assert(!is(typeof({          immutable S a; popFront(a); })));
2375         static assert(!is(typeof({ typeof(S.init[0])[4] a; popFront(a); })));
2376     }}
2377 
2378     C[] _eatString(C)(C[] str)
2379     {
2380         while (!str.empty)
2381             str.popFront();
2382 
2383         return str;
2384     }
2385     enum checkCTFE = _eatString("ウェブサイト@La_Verité.com");
2386     static assert(checkCTFE.empty);
2387     enum checkCTFEW = _eatString("ウェブサイト@La_Verité.com"w);
2388     static assert(checkCTFEW.empty);
2389 }
2390 
2391 // https://issues.dlang.org/show_bug.cgi?id=16090
2392 @safe unittest
2393 {
2394     string s = "\u00E4";
2395     assert(s.length == 2);
2396     s = s[0 .. 1];
2397     assert(s.length == 1);
2398     s.popFront;
2399     assert(s.empty);
2400 }
2401 
2402 @safe unittest
2403 {
2404     wstring s = "\U00010000";
2405     assert(s.length == 2);
2406     s = s[0 .. 1];
2407     assert(s.length == 1);
2408     s.popFront;
2409     assert(s.empty);
2410 }
2411 
2412 /**
2413 Implements the range interface primitive `popBack` for built-in
2414 arrays. Due to the fact that nonmember functions can be called with
2415 the first argument using the dot notation, `array.popBack` is
2416 equivalent to `popBack(array)`. For $(GLOSSARY narrow strings), $(D
2417 popFront) automatically eliminates the last $(GLOSSARY code point).
2418 */
2419 void popBack(T)(scope ref inout(T)[] a) @safe pure nothrow @nogc
2420 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2421 {
2422     assert(a.length);
2423     a = a[0 .. $ - 1];
2424 }
2425 
2426 ///
2427 @safe pure nothrow unittest
2428 {
2429     auto a = [ 1, 2, 3 ];
2430     a.popBack();
2431     assert(a == [ 1, 2 ]);
2432 }
2433 
2434 @safe unittest
2435 {
2436     static assert(!is(typeof({ immutable int[] a; popBack(a); })));
2437     static assert(!is(typeof({          int[4] a; popBack(a); })));
2438     static assert(!is(typeof({          void[] a; popBack(a); })));
2439 }
2440 
2441 /// ditto
2442 void popBack(T)(scope ref inout(T)[] a) @safe pure
2443 if (isAutodecodableString!(T[]))
2444 {
2445     import std.utf : strideBack;
2446     assert(a.length, "Attempting to popBack() past the front of an array of " ~ T.stringof);
2447     a = a[0 .. $ - strideBack(a, $)];
2448 }
2449 
2450 @safe pure unittest
2451 {
2452     import std.meta : AliasSeq;
2453 
2454     static foreach (S; AliasSeq!(string, wstring, dstring))
2455     {{
2456         S s = "hello\xE2\x89\xA0";
2457         s.popBack();
2458         assert(s == "hello");
2459         S s3 = "\xE2\x89\xA0";
2460         auto c = s3.back;
2461         assert(c == cast(dchar)'\u2260');
2462         s3.popBack();
2463         assert(s3 == "");
2464 
2465         S str = "\U00010143\u0100\U00010143hello";
2466         foreach (dchar ch; ['o', 'l', 'l', 'e', 'h', '\U00010143', '\u0100', '\U00010143'])
2467         {
2468             assert(str.back == ch);
2469             str.popBack();
2470         }
2471         assert(str.empty);
2472 
2473         static assert(!is(typeof({          immutable S a; popBack(a); })));
2474         static assert(!is(typeof({ typeof(S.init[0])[4] a; popBack(a); })));
2475     }}
2476 }
2477 
2478 /**
2479 EXPERIMENTAL: to try out removing autodecoding, set the version
2480 `NoAutodecodeStrings`. Most things are expected to fail with this version
2481 currently.
2482 */
2483 version (NoAutodecodeStrings)
2484 {
2485     enum autodecodeStrings = false;
2486 }
2487 else
2488 {
2489     ///
2490     enum autodecodeStrings = true;
2491 }
2492 
2493 /**
2494 Implements the range interface primitive `front` for built-in
2495 arrays. Due to the fact that nonmember functions can be called with
2496 the first argument using the dot notation, `array.front` is
2497 equivalent to `front(array)`. For $(GLOSSARY narrow strings), $(D
2498 front) automatically returns the first $(GLOSSARY code point) as _a $(D
2499 dchar).
2500 */
2501 @property ref inout(T) front(T)(return scope inout(T)[] a) @safe pure nothrow @nogc
2502 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2503 {
2504     assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof);
2505     return a[0];
2506 }
2507 
2508 ///
2509 @safe pure nothrow unittest
2510 {
2511     int[] a = [ 1, 2, 3 ];
2512     assert(a.front == 1);
2513 }
2514 
2515 @safe pure nothrow unittest
2516 {
2517     auto a = [ 1, 2 ];
2518     a.front = 4;
2519     assert(a.front == 4);
2520     assert(a == [ 4, 2 ]);
2521 
2522     immutable b = [ 1, 2 ];
2523     assert(b.front == 1);
2524 
2525     int[2] c = [ 1, 2 ];
2526     assert(c.front == 1);
2527 }
2528 
2529 /// ditto
2530 @property dchar front(T)(scope const(T)[] a) @safe pure
2531 if (isAutodecodableString!(T[]))
2532 {
2533     import std.utf : decode;
2534     assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof);
2535     size_t i = 0;
2536     return decode(a, i);
2537 }
2538 
2539 /**
2540 Implements the range interface primitive `back` for built-in
2541 arrays. Due to the fact that nonmember functions can be called with
2542 the first argument using the dot notation, `array.back` is
2543 equivalent to `back(array)`. For $(GLOSSARY narrow strings), $(D
2544 back) automatically returns the last $(GLOSSARY code point) as _a $(D
2545 dchar).
2546 */
2547 @property ref inout(T) back(T)(return scope inout(T)[] a) @safe pure nothrow @nogc
2548 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2549 {
2550     assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof);
2551     return a[$ - 1];
2552 }
2553 
2554 ///
2555 @safe pure nothrow unittest
2556 {
2557     int[] a = [ 1, 2, 3 ];
2558     assert(a.back == 3);
2559     a.back += 4;
2560     assert(a.back == 7);
2561 }
2562 
2563 @safe pure nothrow unittest
2564 {
2565     immutable b = [ 1, 2, 3 ];
2566     assert(b.back == 3);
2567 
2568     int[3] c = [ 1, 2, 3 ];
2569     assert(c.back == 3);
2570 }
2571 
2572 /// ditto
2573 // Specialization for strings
2574 @property dchar back(T)(scope const(T)[] a) @safe pure
2575 if (isAutodecodableString!(T[]))
2576 {
2577     import std.utf : decode, strideBack;
2578     assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof);
2579     size_t i = a.length - strideBack(a, a.length);
2580     return decode(a, i);
2581 }
2582 
2583 /*
2584 Implements `length` for a range by forwarding it to `member`.
2585 */
2586 package(std) mixin template ImplementLength(alias member)
2587 {
2588     static if (hasLength!(typeof(member)))
2589     {
2590         @property auto length()
2591         {
2592             return member.length;
2593         }
2594         alias opDollar = length;
2595     }
2596 }
2597 
2598 @safe unittest
2599 {
2600     import std.meta : AliasSeq;
2601 
2602     foreach (alias E; AliasSeq!(noreturn, const(noreturn), immutable(noreturn) ))
2603     {
2604         alias R = E[];
2605 
2606         static assert(isInputRange!R);
2607         static assert(isForwardRange!R);
2608         static assert(isBidirectionalRange!R);
2609         static assert(isRandomAccessRange!R);
2610     }
2611 
2612     static assert(isOutputRange!(noreturn[], noreturn));
2613 }