The OpenD Programming Language

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 /// ditto
1019 enum bool isForwardRange(R, E) =
1020     .isForwardRange!R && isQualifierConvertible!(ElementType!R, E);
1021 
1022 ///
1023 @safe unittest
1024 {
1025     static assert(!isForwardRange!(int));
1026     static assert( isForwardRange!(int[]));
1027     static assert( isForwardRange!(inout(int)[]));
1028 
1029     static assert( isForwardRange!(int[], const int));
1030     static assert(!isForwardRange!(int[], immutable int));
1031 
1032     static assert(!isForwardRange!(const(int)[], int));
1033     static assert( isForwardRange!(const(int)[], const int));
1034     static assert(!isForwardRange!(const(int)[], immutable int));
1035 
1036     static assert(!isForwardRange!(immutable(int)[], int));
1037     static assert( isForwardRange!(immutable(int)[], const int));
1038     static assert( isForwardRange!(immutable(int)[], immutable int));
1039 }
1040 
1041 @safe unittest
1042 {
1043     // BUG 14544
1044     struct R14544
1045     {
1046         int front() { return 0;}
1047         void popFront() {}
1048         bool empty() { return false; }
1049         R14544 save() {return this;}
1050     }
1051 
1052     static assert( isForwardRange!R14544 );
1053 }
1054 
1055 /**
1056 Returns `true` if `R` is a bidirectional range. A bidirectional
1057 range is a forward range that also offers the primitives `back` and
1058 `popBack`. The following code should compile for any bidirectional
1059 range.
1060 
1061 The semantics of a bidirectional range (not checkable during
1062 compilation) are assumed to be the following (`r` is an object of
1063 type `R`):
1064 
1065 $(UL $(LI `r.back` returns (possibly a reference to) the last
1066 element in the range. Calling `r.back` is allowed only if calling
1067 `r.empty` has, or would have, returned `false`.))
1068 
1069 See_Also:
1070     The header of $(MREF std,range) for tutorials on ranges.
1071  */
1072 enum bool isBidirectionalRange(R) = isForwardRange!R
1073     && is(typeof((R r) => r.popBack))
1074     && (is(typeof((return ref R r) => r.back)) || is(typeof(ref (return ref R r) => r.back)))
1075     && is(typeof(R.init.back.init) == ElementType!R);
1076 
1077 ///
1078 @safe unittest
1079 {
1080     alias R = int[];
1081     R r = [0,1];
1082     static assert(isForwardRange!R);           // is forward range
1083     r.popBack();                               // can invoke popBack
1084     auto t = r.back;                           // can get the back of the range
1085     auto w = r.front;
1086     static assert(is(typeof(t) == typeof(w))); // same type for front and back
1087 }
1088 
1089 @safe unittest
1090 {
1091     struct A {}
1092     struct B
1093     {
1094         void popFront();
1095         @property bool empty();
1096         @property int front();
1097     }
1098     struct C
1099     {
1100         @property bool empty();
1101         @property C save();
1102         void popFront();
1103         @property int front();
1104         void popBack();
1105         @property int back();
1106     }
1107     static assert(!isBidirectionalRange!(A));
1108     static assert(!isBidirectionalRange!(B));
1109     static assert( isBidirectionalRange!(C));
1110     static assert( isBidirectionalRange!(int[]));
1111     static assert( isBidirectionalRange!(char[]));
1112     static assert( isBidirectionalRange!(inout(int)[]));
1113 }
1114 
1115 /**
1116 Returns `true` if `R` is a random-access range. A random-access
1117 range is a bidirectional range that also offers the primitive $(D
1118 opIndex), OR an infinite forward range that offers `opIndex`. In
1119 either case, the range must either offer `length` or be
1120 infinite. The following code should compile for any random-access
1121 range.
1122 
1123 The semantics of a random-access range (not checkable during
1124 compilation) are assumed to be the following (`r` is an object of
1125 type `R`): $(UL $(LI `r.opIndex(n)` returns a reference to the
1126 `n`th element in the range.))
1127 
1128 Although `char[]` and `wchar[]` (as well as their qualified
1129 versions including `string` and `wstring`) are arrays, $(D
1130 isRandomAccessRange) yields `false` for them because they use
1131 variable-length encodings (UTF-8 and UTF-16 respectively). These types
1132 are bidirectional ranges only.
1133 
1134 See_Also:
1135     The header of $(MREF std,range) for tutorials on ranges.
1136  */
1137 enum bool isRandomAccessRange(R) =
1138     is(typeof(lvalueOf!R[1]) == ElementType!R)
1139     && !(isAutodecodableString!R && !isAggregateType!R)
1140     && isForwardRange!R
1141     && (isBidirectionalRange!R || isInfinite!R)
1142     && (hasLength!R || isInfinite!R)
1143     && (isInfinite!R || !is(typeof(lvalueOf!R[$ - 1]))
1144         || is(typeof(lvalueOf!R[$ - 1]) == ElementType!R));
1145 
1146 ///
1147 @safe unittest
1148 {
1149     import std.traits : isAggregateType, isAutodecodableString;
1150 
1151     alias R = int[];
1152 
1153     // range is finite and bidirectional or infinite and forward.
1154     static assert(isBidirectionalRange!R ||
1155                   isForwardRange!R && isInfinite!R);
1156 
1157     R r = [0,1];
1158     auto e = r[1]; // can index
1159     auto f = r.front;
1160     static assert(is(typeof(e) == typeof(f))); // same type for indexed and front
1161     static assert(!(isAutodecodableString!R && !isAggregateType!R)); // narrow strings cannot be indexed as ranges
1162     static assert(hasLength!R || isInfinite!R); // must have length or be infinite
1163 
1164     // $ must work as it does with arrays if opIndex works with $
1165     static if (is(typeof(r[$])))
1166     {
1167         static assert(is(typeof(f) == typeof(r[$])));
1168 
1169         // $ - 1 doesn't make sense with infinite ranges but needs to work
1170         // with finite ones.
1171         static if (!isInfinite!R)
1172             static assert(is(typeof(f) == typeof(r[$ - 1])));
1173     }
1174 }
1175 
1176 @safe unittest
1177 {
1178     struct A {}
1179     struct B
1180     {
1181         void popFront();
1182         @property bool empty();
1183         @property int front();
1184     }
1185     struct C
1186     {
1187         void popFront();
1188         @property bool empty();
1189         @property int front();
1190         void popBack();
1191         @property int back();
1192     }
1193     struct D
1194     {
1195         @property bool empty();
1196         @property D save();
1197         @property int front();
1198         void popFront();
1199         @property int back();
1200         void popBack();
1201         ref int opIndex(uint);
1202         @property size_t length();
1203         alias opDollar = length;
1204         //int opSlice(uint, uint);
1205     }
1206     struct E
1207     {
1208         bool empty();
1209         E save();
1210         int front();
1211         void popFront();
1212         int back();
1213         void popBack();
1214         ref int opIndex(uint);
1215         size_t length();
1216         alias opDollar = length;
1217         //int opSlice(uint, uint);
1218     }
1219     static assert(!isRandomAccessRange!(A));
1220     static assert(!isRandomAccessRange!(B));
1221     static assert(!isRandomAccessRange!(C));
1222     static assert( isRandomAccessRange!(D));
1223     static assert( isRandomAccessRange!(E));
1224     static assert( isRandomAccessRange!(int[]));
1225     static assert( isRandomAccessRange!(inout(int)[]));
1226 }
1227 
1228 @safe unittest
1229 {
1230     // Test fix for bug 6935.
1231     struct R
1232     {
1233         @disable this();
1234 
1235         @property bool empty() const { return false; }
1236         @property int front() const { return 0; }
1237         void popFront() {}
1238 
1239         @property R save() { return this; }
1240 
1241         @property int back() const { return 0; }
1242         void popBack(){}
1243 
1244         int opIndex(size_t n) const { return 0; }
1245         @property size_t length() const { return 0; }
1246         alias opDollar = length;
1247 
1248         void put(int e){  }
1249     }
1250     static assert(isInputRange!R);
1251     static assert(isForwardRange!R);
1252     static assert(isBidirectionalRange!R);
1253     static assert(isRandomAccessRange!R);
1254     static assert(isOutputRange!(R, int));
1255 }
1256 
1257 /**
1258 Returns `true` iff `R` is an input range that supports the
1259 `moveFront` primitive, as well as `moveBack` and `moveAt` if it's a
1260 bidirectional or random access range. These may be explicitly implemented, or
1261 may work via the default behavior of the module level functions `moveFront`
1262 and friends. The following code should compile for any range
1263 with mobile elements.
1264 
1265 ----
1266 alias E = ElementType!R;
1267 R r;
1268 static assert(isInputRange!R);
1269 static assert(is(typeof(moveFront(r)) == E));
1270 static if (isBidirectionalRange!R)
1271     static assert(is(typeof(moveBack(r)) == E));
1272 static if (isRandomAccessRange!R)
1273     static assert(is(typeof(moveAt(r, 0)) == E));
1274 ----
1275  */
1276 enum bool hasMobileElements(R) =
1277     isInputRange!R
1278     && is(typeof(moveFront(lvalueOf!R)) == ElementType!R)
1279     && (!isBidirectionalRange!R
1280         || is(typeof(moveBack(lvalueOf!R)) == ElementType!R))
1281     && (!isRandomAccessRange!R
1282         || is(typeof(moveAt(lvalueOf!R, 0)) == ElementType!R));
1283 
1284 ///
1285 @safe unittest
1286 {
1287     import std.algorithm.iteration : map;
1288     import std.range : iota, repeat;
1289 
1290     static struct HasPostblit
1291     {
1292         this(this) {}
1293     }
1294 
1295     auto nonMobile = map!"a"(repeat(HasPostblit.init));
1296     static assert(!hasMobileElements!(typeof(nonMobile)));
1297     static assert( hasMobileElements!(int[]));
1298     static assert( hasMobileElements!(inout(int)[]));
1299     static assert( hasMobileElements!(typeof(iota(1000))));
1300 
1301     static assert( hasMobileElements!( string));
1302     static assert( hasMobileElements!(dstring));
1303     static assert( hasMobileElements!( char[]));
1304     static assert( hasMobileElements!(dchar[]));
1305 }
1306 
1307 /**
1308 The element type of `R`. `R` does not have to be a range. The
1309 element type is determined as the type yielded by `r.front` for an
1310 object `r` of type `R`. For example, `ElementType!(T[])` is
1311 `T` if `T[]` isn't a narrow string; if it is, the element type is
1312 `dchar`. If `R` doesn't have `front`, `ElementType!R` is
1313 `void`.
1314  */
1315 template ElementType(R)
1316 {
1317     static if (is(typeof(R.init.front.init) T))
1318         alias ElementType = T;
1319     else
1320         alias ElementType = void;
1321 }
1322 
1323 ///
1324 @safe unittest
1325 {
1326     import std.range : iota;
1327 
1328     // Standard arrays: returns the type of the elements of the array
1329     static assert(is(ElementType!(int[]) == int));
1330 
1331     // Accessing .front retrieves the decoded dchar
1332     static assert(is(ElementType!(char[])  == dchar)); // rvalue
1333     static assert(is(ElementType!(dchar[]) == dchar)); // lvalue
1334 
1335     // Ditto
1336     static assert(is(ElementType!(string) == dchar));
1337     static assert(is(ElementType!(dstring) == immutable(dchar)));
1338 
1339     // For ranges it gets the type of .front.
1340     auto range = iota(0, 10);
1341     static assert(is(ElementType!(typeof(range)) == int));
1342 }
1343 
1344 @safe unittest
1345 {
1346     static assert(is(ElementType!(byte[]) == byte));
1347     static assert(is(ElementType!(wchar[]) == dchar)); // rvalue
1348     static assert(is(ElementType!(wstring) == dchar));
1349 }
1350 
1351 @safe unittest
1352 {
1353     enum XYZ : string { a = "foo" }
1354     auto x = XYZ.a.front;
1355     immutable char[3] a = "abc";
1356     int[] i;
1357     void[] buf;
1358     static assert(is(ElementType!(XYZ) == dchar));
1359     static assert(is(ElementType!(typeof(a)) == dchar));
1360     static assert(is(ElementType!(typeof(i)) == int));
1361     static assert(is(ElementType!(typeof(buf)) == void));
1362     static assert(is(ElementType!(inout(int)[]) == inout(int)));
1363     static assert(is(ElementType!(inout(int[])) == inout(int)));
1364 }
1365 
1366 @safe unittest
1367 {
1368     static assert(is(ElementType!(int[5]) == int));
1369     static assert(is(ElementType!(int[0]) == int));
1370     static assert(is(ElementType!(char[5]) == dchar));
1371     static assert(is(ElementType!(char[0]) == dchar));
1372 }
1373 
1374 // https://issues.dlang.org/show_bug.cgi?id=11336
1375 @safe unittest
1376 {
1377     static struct S
1378     {
1379         this(this) @disable;
1380     }
1381     static assert(is(ElementType!(S[]) == S));
1382 }
1383 
1384 // https://issues.dlang.org/show_bug.cgi?id=11401
1385 @safe unittest
1386 {
1387     // ElementType should also work for non-@propety 'front'
1388     struct E { ushort id; }
1389     struct R
1390     {
1391         E front() { return E.init; }
1392     }
1393     static assert(is(ElementType!R == E));
1394 }
1395 
1396 /**
1397 The encoding element type of `R`. For narrow strings (`char[]`,
1398 `wchar[]` and their qualified variants including `string` and
1399 `wstring`), `ElementEncodingType` is the character type of the
1400 string. For all other types, `ElementEncodingType` is the same as
1401 `ElementType`.
1402  */
1403 template ElementEncodingType(R)
1404 {
1405     static if (is(StringTypeOf!R) && is(R : E[], E))
1406         alias ElementEncodingType = E;
1407     else
1408         alias ElementEncodingType = ElementType!R;
1409 }
1410 
1411 ///
1412 @safe unittest
1413 {
1414     import std.range : iota;
1415     // internally the range stores the encoded type
1416     static assert(is(ElementEncodingType!(char[])  == char));
1417 
1418     static assert(is(ElementEncodingType!(wstring) == immutable(wchar)));
1419 
1420     static assert(is(ElementEncodingType!(byte[]) == byte));
1421 
1422     auto range = iota(0, 10);
1423     static assert(is(ElementEncodingType!(typeof(range)) == int));
1424 }
1425 
1426 @safe unittest
1427 {
1428     static assert(is(ElementEncodingType!(wchar[]) == wchar));
1429     static assert(is(ElementEncodingType!(dchar[]) == dchar));
1430     static assert(is(ElementEncodingType!(string)  == immutable(char)));
1431     static assert(is(ElementEncodingType!(dstring) == immutable(dchar)));
1432     static assert(is(ElementEncodingType!(int[])  == int));
1433 }
1434 
1435 @safe unittest
1436 {
1437     enum XYZ : string { a = "foo" }
1438     auto x = XYZ.a.front;
1439     immutable char[3] a = "abc";
1440     int[] i;
1441     void[] buf;
1442     static assert(is(ElementType!(XYZ) : dchar));
1443     static assert(is(ElementEncodingType!(char[]) == char));
1444     static assert(is(ElementEncodingType!(string) == immutable char));
1445     static assert(is(ElementType!(typeof(a)) : dchar));
1446     static assert(is(ElementType!(typeof(i)) == int));
1447     static assert(is(ElementEncodingType!(typeof(i)) == int));
1448     static assert(is(ElementType!(typeof(buf)) : void));
1449 
1450     static assert(is(ElementEncodingType!(inout char[]) : inout(char)));
1451 }
1452 
1453 @safe unittest
1454 {
1455     static assert(is(ElementEncodingType!(int[5]) == int));
1456     static assert(is(ElementEncodingType!(int[0]) == int));
1457     static assert(is(ElementEncodingType!(char[5]) == char));
1458     static assert(is(ElementEncodingType!(char[0]) == char));
1459 }
1460 
1461 /**
1462 Returns `true` if `R` is an input range and has swappable
1463 elements. The following code should compile for any range
1464 with swappable elements.
1465 
1466 ----
1467 R r;
1468 static assert(isInputRange!R);
1469 swap(r.front, r.front);
1470 static if (isBidirectionalRange!R) swap(r.back, r.front);
1471 static if (isRandomAccessRange!R) swap(r[0], r.front);
1472 ----
1473  */
1474 template hasSwappableElements(R)
1475 {
1476     import std.algorithm.mutation : swap;
1477     enum bool hasSwappableElements = isInputRange!R
1478         && is(typeof((ref R r) => swap(r.front, r.front)))
1479         && (!isBidirectionalRange!R
1480             || is(typeof((ref R r) => swap(r.back, r.front))))
1481         && (!isRandomAccessRange!R
1482             || is(typeof((ref R r) => swap(r[0], r.front))));
1483 }
1484 
1485 ///
1486 @safe unittest
1487 {
1488     static assert(!hasSwappableElements!(const int[]));
1489     static assert(!hasSwappableElements!(const(int)[]));
1490     static assert(!hasSwappableElements!(inout(int)[]));
1491     static assert( hasSwappableElements!(int[]));
1492 
1493     static assert(!hasSwappableElements!( string));
1494     static assert(!hasSwappableElements!(dstring));
1495     static assert(!hasSwappableElements!( char[]));
1496     static assert( hasSwappableElements!(dchar[]));
1497 }
1498 
1499 /**
1500 Returns `true` if `R` is an input range and has mutable
1501 elements. The following code should compile for any range
1502 with assignable elements.
1503 
1504 ----
1505 R r;
1506 static assert(isInputRange!R);
1507 r.front = r.front;
1508 static if (isBidirectionalRange!R) r.back = r.front;
1509 static if (isRandomAccessRange!R) r[0] = r.front;
1510 ----
1511  */
1512 enum bool hasAssignableElements(R) = isInputRange!R
1513     && is(typeof(lvalueOf!R.front = lvalueOf!R.front))
1514     && (!isBidirectionalRange!R
1515         || is(typeof(lvalueOf!R.back = lvalueOf!R.back)))
1516     && (!isRandomAccessRange!R
1517         || is(typeof(lvalueOf!R[0] = lvalueOf!R.front)));
1518 
1519 ///
1520 @safe unittest
1521 {
1522     static assert(!hasAssignableElements!(const int[]));
1523     static assert(!hasAssignableElements!(const(int)[]));
1524     static assert( hasAssignableElements!(int[]));
1525     static assert(!hasAssignableElements!(inout(int)[]));
1526 
1527     static assert(!hasAssignableElements!( string));
1528     static assert(!hasAssignableElements!(dstring));
1529     static assert(!hasAssignableElements!( char[]));
1530     static assert( hasAssignableElements!(dchar[]));
1531 }
1532 
1533 /**
1534 Tests whether the range `R` has lvalue elements. These are defined as
1535 elements that can be passed by reference and have their address taken.
1536 The following code should compile for any range with lvalue elements.
1537 ----
1538 void passByRef(ref ElementType!R stuff);
1539 ...
1540 static assert(isInputRange!R);
1541 passByRef(r.front);
1542 static if (isBidirectionalRange!R) passByRef(r.back);
1543 static if (isRandomAccessRange!R) passByRef(r[0]);
1544 ----
1545 */
1546 enum bool hasLvalueElements(R) = isInputRange!R
1547     && is(typeof(isLvalue(lvalueOf!R.front)))
1548     && (!isBidirectionalRange!R
1549         || is(typeof(isLvalue(lvalueOf!R.back))))
1550     && (!isRandomAccessRange!R
1551         || is(typeof(isLvalue(lvalueOf!R[0]))));
1552 
1553 /* Compile successfully if argument of type T is an lvalue
1554  */
1555 private void isLvalue(T)(T)
1556 if (0);
1557 
1558 private void isLvalue(T)(ref T)
1559 if (1);
1560 
1561 ///
1562 @safe unittest
1563 {
1564     import std.range : iota, chain;
1565 
1566     static assert( hasLvalueElements!(int[]));
1567     static assert( hasLvalueElements!(const(int)[]));
1568     static assert( hasLvalueElements!(inout(int)[]));
1569     static assert( hasLvalueElements!(immutable(int)[]));
1570     static assert(!hasLvalueElements!(typeof(iota(3))));
1571 
1572     static assert(!hasLvalueElements!( string));
1573     static assert( hasLvalueElements!(dstring));
1574     static assert(!hasLvalueElements!( char[]));
1575     static assert( hasLvalueElements!(dchar[]));
1576 
1577     auto c = chain([1, 2, 3], [4, 5, 6]);
1578     static assert( hasLvalueElements!(typeof(c)));
1579 }
1580 
1581 @safe unittest
1582 {
1583     // bugfix 6336
1584     struct S { immutable int value; }
1585     static assert( isInputRange!(S[]));
1586     static assert( hasLvalueElements!(S[]));
1587 }
1588 
1589 /**
1590 Yields `true` if `R` has a `length` member that returns a value of `size_t`
1591 type. `R` does not have to be a range. If `R` is a range, algorithms in the
1592 standard library are only guaranteed to support `length` with type `size_t`.
1593 
1594 Note that `length` is an optional primitive as no range must implement it. Some
1595 ranges do not store their length explicitly, some cannot compute it without
1596 actually exhausting the range (e.g. socket streams), and some other ranges may
1597 be infinite.
1598 
1599 Although narrow string types (`char[]`, `wchar[]`, and their qualified
1600 derivatives) do define a `length` property, `hasLength` yields `false` for them.
1601 This is because a narrow string's length does not reflect the number of
1602 characters, but instead the number of encoding units, and as such is not useful
1603 with range-oriented algorithms. To use strings as random-access ranges with
1604 length, use $(REF representation, std, string) or $(REF byCodeUnit, std, utf).
1605 */
1606 template hasLength(R)
1607 {
1608     static if (is(typeof(((R* r) => r.length)(null)) Length))
1609         enum bool hasLength = is(Length == size_t) &&
1610                               !(isAutodecodableString!R && !isAggregateType!R);
1611     else
1612         enum bool hasLength = false;
1613 }
1614 
1615 ///
1616 @safe unittest
1617 {
1618     static assert(!hasLength!(char[]));
1619     static assert( hasLength!(int[]));
1620     static assert( hasLength!(inout(int)[]));
1621 
1622     struct A { size_t length() { return 0; } }
1623     struct B { @property size_t length() { return 0; } }
1624     static assert( hasLength!(A));
1625     static assert( hasLength!(B));
1626 }
1627 
1628 // test combinations which are invalid on some platforms
1629 @safe unittest
1630 {
1631     struct A { ulong length; }
1632     struct B { @property uint length() { return 0; } }
1633 
1634     static if (is(size_t == uint))
1635     {
1636         static assert(!hasLength!(A));
1637         static assert(hasLength!(B));
1638     }
1639     else static if (is(size_t == ulong))
1640     {
1641         static assert(hasLength!(A));
1642         static assert(!hasLength!(B));
1643     }
1644 }
1645 
1646 // test combinations which are invalid on all platforms
1647 @safe unittest
1648 {
1649     struct A { long length; }
1650     struct B { int length; }
1651     struct C { ubyte length; }
1652     struct D { char length; }
1653     static assert(!hasLength!(A));
1654     static assert(!hasLength!(B));
1655     static assert(!hasLength!(C));
1656     static assert(!hasLength!(D));
1657 }
1658 
1659 /**
1660 Returns `true` if `R` is an infinite input range. An
1661 infinite input range is an input range that has a statically-defined
1662 enumerated member called `empty` that is always `false`,
1663 for example:
1664 
1665 ----
1666 struct MyInfiniteRange
1667 {
1668     enum bool empty = false;
1669     ...
1670 }
1671 ----
1672  */
1673 
1674 template isInfinite(R)
1675 {
1676     static if (isInputRange!R && __traits(compiles, { enum e = R.empty; }))
1677         enum bool isInfinite = !R.empty;
1678     else
1679         enum bool isInfinite = false;
1680 }
1681 
1682 ///
1683 @safe unittest
1684 {
1685     import std.range : Repeat;
1686     static assert(!isInfinite!(int[]));
1687     static assert( isInfinite!(Repeat!(int)));
1688 }
1689 
1690 /**
1691 Returns `true` if `R` offers a slicing operator with integral boundaries
1692 that returns a forward range type.
1693 
1694 For finite ranges, the result of `opSlice` must be of the same type as the
1695 original range type. If the range defines `opDollar`, then it must support
1696 subtraction.
1697 
1698 For infinite ranges, when $(I not) using `opDollar`, the result of
1699 `opSlice` must be the result of $(LREF take) or $(LREF takeExactly) on the
1700 original range (they both return the same type for infinite ranges). However,
1701 when using `opDollar`, the result of `opSlice` must be that of the
1702 original range type.
1703 
1704 The following expression must be true for `hasSlicing` to be `true`:
1705 
1706 ----
1707     isForwardRange!R
1708     && !(isAutodecodableString!R && !isAggregateType!R)
1709     && is(typeof((R r) { return r[1 .. 1].length; } (R.init)) == size_t)
1710     && (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R)
1711     && (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R))
1712     && (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R
1713         || is(typeof(lvalueOf!R[0 .. $ - 1]) == R))
1714     && is(typeof((ref R r)
1715     {
1716         static assert(isForwardRange!(typeof(r[1 .. 2])));
1717     }));
1718 ----
1719  */
1720 enum bool hasSlicing(R) = isForwardRange!R
1721     && !(isAutodecodableString!R && !isAggregateType!R)
1722     && is(typeof((R r) { return r[1 .. 1].length; } (R.init)) == size_t)
1723     && (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R)
1724     && (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R))
1725     && (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R
1726         || is(typeof(lvalueOf!R[0 .. $ - 1]) == R))
1727     && is(typeof((ref R r)
1728     {
1729         static assert(isForwardRange!(typeof(r[1 .. 2])));
1730     }));
1731 
1732 ///
1733 @safe unittest
1734 {
1735     import std.range : takeExactly;
1736     static assert( hasSlicing!(int[]));
1737     static assert( hasSlicing!(const(int)[]));
1738     static assert(!hasSlicing!(const int[]));
1739     static assert( hasSlicing!(inout(int)[]));
1740     static assert(!hasSlicing!(inout int []));
1741     static assert( hasSlicing!(immutable(int)[]));
1742     static assert(!hasSlicing!(immutable int[]));
1743     static assert(!hasSlicing!string);
1744     static assert( hasSlicing!dstring);
1745 
1746     enum rangeFuncs = "@property int front();" ~
1747                       "void popFront();" ~
1748                       "@property bool empty();" ~
1749                       "@property auto save() { return this; }" ~
1750                       "@property size_t length();";
1751 
1752     struct A { mixin(rangeFuncs); int opSlice(size_t, size_t); }
1753     struct B { mixin(rangeFuncs); B opSlice(size_t, size_t); }
1754     struct C { mixin(rangeFuncs); @disable this(); C opSlice(size_t, size_t); }
1755     struct D { mixin(rangeFuncs); int[] opSlice(size_t, size_t); }
1756     static assert(!hasSlicing!(A));
1757     static assert( hasSlicing!(B));
1758     static assert( hasSlicing!(C));
1759     static assert(!hasSlicing!(D));
1760 
1761     struct InfOnes
1762     {
1763         enum empty = false;
1764         void popFront() {}
1765         @property int front() { return 1; }
1766         @property InfOnes save() { return this; }
1767         auto opSlice(size_t i, size_t j) { return takeExactly(this, j - i); }
1768         auto opSlice(size_t i, Dollar d) { return this; }
1769 
1770         struct Dollar {}
1771         Dollar opDollar() const { return Dollar.init; }
1772     }
1773 
1774     static assert(hasSlicing!InfOnes);
1775 }
1776 
1777 /**
1778 This is a best-effort implementation of `length` for any kind of
1779 range.
1780 
1781 If `hasLength!Range`, simply returns `range.length` without
1782 checking `upTo` (when specified).
1783 
1784 Otherwise, walks the range through its length and returns the number
1785 of elements seen. Performes $(BIGOH n) evaluations of `range.empty`
1786 and `range.popFront()`, where `n` is the effective length of $(D
1787 range).
1788 
1789 The `upTo` parameter is useful to "cut the losses" in case
1790 the interest is in seeing whether the range has at least some number
1791 of elements. If the parameter `upTo` is specified, stops if $(D
1792 upTo) steps have been taken and returns `upTo`.
1793 
1794 Infinite ranges are compatible, provided the parameter `upTo` is
1795 specified, in which case the implementation simply returns upTo.
1796  */
1797 auto walkLength(Range)(Range range)
1798 if (isInputRange!Range && !isInfinite!Range)
1799 {
1800     static if (hasLength!Range)
1801         return range.length;
1802     else
1803     {
1804         size_t result;
1805         static if (autodecodeStrings && isNarrowString!Range)
1806         {
1807             import std.utf : codeUnitLimit;
1808             result = range.length;
1809             foreach (const i, const c; range)
1810             {
1811                 if (c >= codeUnitLimit!Range)
1812                 {
1813                     result = i;
1814                     break;
1815                 }
1816             }
1817             range = range[result .. $];
1818         }
1819         for ( ; !range.empty ; range.popFront() )
1820             ++result;
1821         return result;
1822     }
1823 }
1824 /// ditto
1825 auto walkLength(Range)(Range range, const size_t upTo)
1826 if (isInputRange!Range)
1827 {
1828     static if (hasLength!Range)
1829         return range.length;
1830     else static if (isInfinite!Range)
1831         return upTo;
1832     else
1833     {
1834         size_t result;
1835         static if (autodecodeStrings && isNarrowString!Range)
1836         {
1837             import std.utf : codeUnitLimit;
1838             result = upTo > range.length ? range.length : upTo;
1839             foreach (const i, const c; range[0 .. result])
1840             {
1841                 if (c >= codeUnitLimit!Range)
1842                 {
1843                     result = i;
1844                     break;
1845                 }
1846             }
1847             range = range[result .. $];
1848         }
1849         for ( ; result < upTo && !range.empty ; range.popFront() )
1850             ++result;
1851         return result;
1852     }
1853 }
1854 
1855 ///
1856 @safe unittest
1857 {
1858     import std.range : iota;
1859 
1860     assert(10.iota.walkLength == 10);
1861     // iota has a length function, and therefore the
1862     // doesn't have to be walked, and the upTo
1863     // parameter is ignored
1864     assert(10.iota.walkLength(5) == 10);
1865 }
1866 
1867 @safe unittest
1868 {
1869     import std.algorithm.iteration : filter;
1870     import std.range : recurrence, take;
1871 
1872     //hasLength Range
1873     int[] a = [ 1, 2, 3 ];
1874     assert(walkLength(a) == 3);
1875     assert(walkLength(a, 0) == 3);
1876     assert(walkLength(a, 2) == 3);
1877     assert(walkLength(a, 4) == 3);
1878 
1879     //Forward Range
1880     auto b = filter!"true"([1, 2, 3, 4]);
1881     assert(b.walkLength() == 4);
1882     assert(b.walkLength(0) == 0);
1883     assert(b.walkLength(2) == 2);
1884     assert(b.walkLength(4) == 4);
1885     assert(b.walkLength(6) == 4);
1886 
1887     //Infinite Range
1888     auto fibs = recurrence!"a[n-1] + a[n-2]"(1, 1);
1889     assert(!__traits(compiles, fibs.walkLength()));
1890     assert(fibs.take(10).walkLength() == 10);
1891     assert(fibs.walkLength(55) == 55);
1892 }
1893 
1894 /**
1895     `popFrontN` eagerly advances `r` itself (not a copy) up to `n` times
1896     (by calling `r.popFront`). `popFrontN` takes `r` by `ref`,
1897     so it mutates the original range. Completes in $(BIGOH 1) steps for ranges
1898     that support slicing and have length.
1899     Completes in $(BIGOH n) time for all other ranges.
1900 
1901     `popBackN` behaves the same as `popFrontN` but instead removes
1902     elements from the back of the (bidirectional) range instead of the front.
1903 
1904     Returns:
1905     How much `r` was actually advanced, which may be less than `n` if
1906     `r` did not have at least `n` elements.
1907 
1908     See_Also: $(REF drop, std, range), $(REF dropBack, std, range)
1909 */
1910 size_t popFrontN(Range)(ref Range r, size_t n)
1911 if (isInputRange!Range)
1912 {
1913     static if (hasLength!Range)
1914     {
1915         n = cast(size_t) (n < r.length ? n : r.length);
1916     }
1917 
1918     static if (hasSlicing!Range && is(typeof(r = r[n .. $])))
1919     {
1920         r = r[n .. $];
1921     }
1922     else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar.
1923     {
1924         r = r[n .. r.length];
1925     }
1926     else
1927     {
1928         static if (hasLength!Range)
1929         {
1930             foreach (i; 0 .. n)
1931                 r.popFront();
1932         }
1933         else
1934         {
1935             foreach (i; 0 .. n)
1936             {
1937                 if (r.empty) return i;
1938                 r.popFront();
1939             }
1940         }
1941     }
1942     return n;
1943 }
1944 
1945 /// ditto
1946 size_t popBackN(Range)(ref Range r, size_t n)
1947 if (isBidirectionalRange!Range)
1948 {
1949     static if (hasLength!Range)
1950     {
1951         n = cast(size_t) (n < r.length ? n : r.length);
1952     }
1953 
1954     static if (hasSlicing!Range && is(typeof(r = r[0 .. $ - n])))
1955     {
1956         r = r[0 .. $ - n];
1957     }
1958     else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar.
1959     {
1960         r = r[0 .. r.length - n];
1961     }
1962     else
1963     {
1964         static if (hasLength!Range)
1965         {
1966             foreach (i; 0 .. n)
1967                 r.popBack();
1968         }
1969         else
1970         {
1971             foreach (i; 0 .. n)
1972             {
1973                 if (r.empty) return i;
1974                 r.popBack();
1975             }
1976         }
1977     }
1978     return n;
1979 }
1980 
1981 ///
1982 @safe unittest
1983 {
1984     int[] a = [ 1, 2, 3, 4, 5 ];
1985     a.popFrontN(2);
1986     assert(a == [ 3, 4, 5 ]);
1987     a.popFrontN(7);
1988     assert(a == [ ]);
1989 }
1990 
1991 ///
1992 @safe unittest
1993 {
1994     import std.algorithm.comparison : equal;
1995     import std.range : iota;
1996     auto LL = iota(1L, 7L);
1997     auto r = popFrontN(LL, 2);
1998     assert(equal(LL, [3L, 4L, 5L, 6L]));
1999     assert(r == 2);
2000 }
2001 
2002 ///
2003 @safe unittest
2004 {
2005     int[] a = [ 1, 2, 3, 4, 5 ];
2006     a.popBackN(2);
2007     assert(a == [ 1, 2, 3 ]);
2008     a.popBackN(7);
2009     assert(a == [ ]);
2010 }
2011 
2012 ///
2013 @safe unittest
2014 {
2015     import std.algorithm.comparison : equal;
2016     import std.range : iota;
2017     auto LL = iota(1L, 7L);
2018     auto r = popBackN(LL, 2);
2019     assert(equal(LL, [1L, 2L, 3L, 4L]));
2020     assert(r == 2);
2021 }
2022 
2023 /**
2024     Eagerly advances `r` itself (not a copy) exactly `n` times (by
2025     calling `r.popFront`). `popFrontExactly` takes `r` by `ref`,
2026     so it mutates the original range. Completes in $(BIGOH 1) steps for ranges
2027     that support slicing, and have either length or are infinite.
2028     Completes in $(BIGOH n) time for all other ranges.
2029 
2030     Note: Unlike $(LREF popFrontN), `popFrontExactly` will assume that the
2031     range holds at least `n` elements. This makes `popFrontExactly`
2032     faster than `popFrontN`, but it also means that if `range` does
2033     not contain at least `n` elements, it will attempt to call `popFront`
2034     on an empty range, which is undefined behavior. So, only use
2035     `popFrontExactly` when it is guaranteed that `range` holds at least
2036     `n` elements.
2037 
2038     `popBackExactly` will behave the same but instead removes elements from
2039     the back of the (bidirectional) range instead of the front.
2040 
2041     See_Also: $(REF dropExactly, std, range), $(REF dropBackExactly, std, range)
2042 */
2043 void popFrontExactly(Range)(ref Range r, size_t n)
2044 if (isInputRange!Range)
2045 {
2046     static if (hasLength!Range)
2047         assert(n <= r.length, "range is smaller than amount of items to pop");
2048 
2049     static if (hasSlicing!Range && is(typeof(r = r[n .. $])))
2050         r = r[n .. $];
2051     else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar.
2052         r = r[n .. r.length];
2053     else
2054         foreach (i; 0 .. n)
2055             r.popFront();
2056 }
2057 
2058 /// ditto
2059 void popBackExactly(Range)(ref Range r, size_t n)
2060 if (isBidirectionalRange!Range)
2061 {
2062     static if (hasLength!Range)
2063         assert(n <= r.length, "range is smaller than amount of items to pop");
2064 
2065     static if (hasSlicing!Range && is(typeof(r = r[0 .. $ - n])))
2066         r = r[0 .. $ - n];
2067     else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar.
2068         r = r[0 .. r.length - n];
2069     else
2070         foreach (i; 0 .. n)
2071             r.popBack();
2072 }
2073 
2074 ///
2075 @safe unittest
2076 {
2077     import std.algorithm.comparison : equal;
2078     import std.algorithm.iteration : filterBidirectional;
2079 
2080     auto a = [1, 2, 3];
2081     a.popFrontExactly(1);
2082     assert(a == [2, 3]);
2083     a.popBackExactly(1);
2084     assert(a == [2]);
2085 
2086     string s = "日本語";
2087     s.popFrontExactly(1);
2088     assert(s == "本語");
2089     s.popBackExactly(1);
2090     assert(s == "本");
2091 
2092     auto bd = filterBidirectional!"true"([1, 2, 3]);
2093     bd.popFrontExactly(1);
2094     assert(bd.equal([2, 3]));
2095     bd.popBackExactly(1);
2096     assert(bd.equal([2]));
2097 }
2098 
2099 /**
2100    Moves the front of `r` out and returns it.
2101 
2102    If `r.front` is a struct with a destructor or copy constructor defined, it
2103    is reset to its `.init` value after its value is moved. Otherwise, it is
2104    left unchanged.
2105 
2106    In either case, `r.front` is left in a destroyable state that does not
2107    allocate any resources.
2108 */
2109 ElementType!R moveFront(R)(R r)
2110 {
2111     static if (is(typeof(&r.moveFront)))
2112     {
2113         return r.moveFront();
2114     }
2115     else static if (!hasElaborateCopyConstructor!(ElementType!R))
2116     {
2117         return r.front;
2118     }
2119     else static if (is(typeof(&(r.front())) == ElementType!R*))
2120     {
2121         import std.algorithm.mutation : move;
2122         return move(r.front);
2123     }
2124     else
2125     {
2126         static assert(0,
2127                 "Cannot move front of a range with a postblit and an rvalue front.");
2128     }
2129 }
2130 
2131 ///
2132 @safe unittest
2133 {
2134     auto a = [ 1, 2, 3 ];
2135     assert(moveFront(a) == 1);
2136     assert(a.length == 3);
2137 
2138     // define a perfunctory input range
2139     struct InputRange
2140     {
2141         enum bool empty = false;
2142         enum int front = 7;
2143         void popFront() {}
2144         int moveFront() { return 43; }
2145     }
2146     InputRange r;
2147     // calls r.moveFront
2148     assert(moveFront(r) == 43);
2149 }
2150 
2151 @safe unittest
2152 {
2153     struct R
2154     {
2155         @property ref int front() { static int x = 42; return x; }
2156         this(this){}
2157     }
2158     R r;
2159     assert(moveFront(r) == 42);
2160 }
2161 
2162 /**
2163    Moves the back of `r` out and returns it. Leaves `r.back` in a
2164    destroyable state that does not allocate any resources (usually equal
2165    to its `.init` value).
2166 */
2167 ElementType!R moveBack(R)(R r)
2168 {
2169     static if (is(typeof(&r.moveBack)))
2170     {
2171         return r.moveBack();
2172     }
2173     else static if (!hasElaborateCopyConstructor!(ElementType!R))
2174     {
2175         return r.back;
2176     }
2177     else static if (is(typeof(&(r.back())) == ElementType!R*))
2178     {
2179         import std.algorithm.mutation : move;
2180         return move(r.back);
2181     }
2182     else
2183     {
2184         static assert(0,
2185                 "Cannot move back of a range with a postblit and an rvalue back.");
2186     }
2187 }
2188 
2189 ///
2190 @safe unittest
2191 {
2192     struct TestRange
2193     {
2194         int payload = 5;
2195         @property bool empty() { return false; }
2196         @property TestRange save() { return this; }
2197         @property ref int front() return { return payload; }
2198         @property ref int back() return { return payload; }
2199         void popFront() { }
2200         void popBack() { }
2201     }
2202     static assert(isBidirectionalRange!TestRange);
2203     TestRange r;
2204     auto x = moveBack(r);
2205     assert(x == 5);
2206 }
2207 
2208 /**
2209    Moves element at index `i` of `r` out and returns it. Leaves $(D
2210    r[i]) in a destroyable state that does not allocate any resources
2211    (usually equal to its `.init` value).
2212 */
2213 ElementType!R moveAt(R)(R r, size_t i)
2214 {
2215     static if (is(typeof(&r.moveAt)))
2216     {
2217         return r.moveAt(i);
2218     }
2219     else static if (!hasElaborateCopyConstructor!(ElementType!(R)))
2220     {
2221         return r[i];
2222     }
2223     else static if (is(typeof(&r[i]) == ElementType!R*))
2224     {
2225         import std.algorithm.mutation : move;
2226         return move(r[i]);
2227     }
2228     else
2229     {
2230         static assert(0,
2231                 "Cannot move element of a range with a postblit and rvalue elements.");
2232     }
2233 }
2234 
2235 ///
2236 @safe unittest
2237 {
2238     auto a = [1,2,3,4];
2239     foreach (idx, it; a)
2240     {
2241         assert(it == moveAt(a, idx));
2242     }
2243 }
2244 
2245 @safe unittest
2246 {
2247     import std.internal.test.dummyrange;
2248 
2249     foreach (DummyType; AllDummyRanges)
2250     {
2251         auto d = DummyType.init;
2252         assert(moveFront(d) == 1);
2253 
2254         static if (isBidirectionalRange!DummyType)
2255         {
2256             assert(moveBack(d) == 10);
2257         }
2258 
2259         static if (isRandomAccessRange!DummyType)
2260         {
2261             assert(moveAt(d, 2) == 3);
2262         }
2263     }
2264 }
2265 
2266 /**
2267 Implements the range interface primitive `empty` for types that
2268 obey $(LREF hasLength) property and for narrow strings. Due to the
2269 fact that nonmember functions can be called with the first argument
2270 using the dot notation, `a.empty` is equivalent to `empty(a)`.
2271  */
2272 @property bool empty(T)(auto ref scope T a)
2273 if (is(typeof(a.length) : size_t))
2274 {
2275     return !a.length;
2276 }
2277 
2278 ///
2279 @safe pure nothrow unittest
2280 {
2281     auto a = [ 1, 2, 3 ];
2282     assert(!a.empty);
2283     assert(a[3 .. $].empty);
2284 
2285     int[string] b;
2286     assert(b.empty);
2287     b["zero"] = 0;
2288     assert(!b.empty);
2289 }
2290 
2291 /**
2292 Implements the range interface primitive `save` for built-in
2293 arrays. Due to the fact that nonmember functions can be called with
2294 the first argument using the dot notation, `array.save` is
2295 equivalent to `save(array)`. The function does not duplicate the
2296 content of the array, it simply returns its argument.
2297  */
2298 @property inout(T)[] save(T)(return scope inout(T)[] a) @safe pure nothrow @nogc
2299 {
2300     return a;
2301 }
2302 
2303 ///
2304 @safe pure nothrow unittest
2305 {
2306     auto a = [ 1, 2, 3 ];
2307     auto b = a.save;
2308     assert(b is a);
2309 }
2310 
2311 /**
2312 Implements the range interface primitive `popFront` for built-in
2313 arrays. Due to the fact that nonmember functions can be called with
2314 the first argument using the dot notation, `array.popFront` is
2315 equivalent to `popFront(array)`. For $(GLOSSARY narrow strings),
2316 `popFront` automatically advances to the next $(GLOSSARY code
2317 point).
2318 */
2319 void popFront(T)(scope ref inout(T)[] a) @safe pure nothrow @nogc
2320 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2321 {
2322     assert(a.length, "Attempting to popFront() past the end of an array of " ~ T.stringof);
2323     a = a[1 .. $];
2324 }
2325 
2326 ///
2327 @safe pure nothrow unittest
2328 {
2329     auto a = [ 1, 2, 3 ];
2330     a.popFront();
2331     assert(a == [ 2, 3 ]);
2332 }
2333 
2334 @safe unittest
2335 {
2336     static assert(!is(typeof({          int[4] a; popFront(a); })));
2337     static assert(!is(typeof({ immutable int[] a; popFront(a); })));
2338     static assert(!is(typeof({          void[] a; popFront(a); })));
2339 }
2340 
2341 /// ditto
2342 void popFront(C)(scope ref inout(C)[] str) @trusted pure nothrow
2343 if (isAutodecodableString!(C[]))
2344 {
2345     import std.algorithm.comparison : min;
2346 
2347     assert(str.length, "Attempting to popFront() past the end of an array of " ~ C.stringof);
2348 
2349     static if (is(immutable C == immutable char))
2350     {
2351         static immutable ubyte[] charWidthTab = [
2352             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2353             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2354             3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2355             4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
2356         ];
2357 
2358         immutable c = str[0];
2359         immutable charWidth = c < 192 ? 1 : charWidthTab.ptr[c - 192];
2360         str = str.ptr[min(str.length, charWidth) .. str.length];
2361     }
2362     else static if (is(immutable C == immutable wchar))
2363     {
2364         immutable u = str[0];
2365         immutable seqLen = 1 + (u >= 0xD800 && u <= 0xDBFF);
2366         str = str.ptr[min(seqLen, str.length) .. str.length];
2367     }
2368     else static assert(0, "Bad template constraint.");
2369 }
2370 
2371 @safe pure unittest
2372 {
2373     import std.meta : AliasSeq;
2374 
2375     static foreach (S; AliasSeq!(string, wstring, dstring))
2376     {{
2377         S s = "\xC2\xA9hello";
2378         s.popFront();
2379         assert(s == "hello");
2380 
2381         S str = "hello\U00010143\u0100\U00010143";
2382         foreach (dchar c; ['h', 'e', 'l', 'l', 'o', '\U00010143', '\u0100', '\U00010143'])
2383         {
2384             assert(str.front == c);
2385             str.popFront();
2386         }
2387         assert(str.empty);
2388 
2389         static assert(!is(typeof({          immutable S a; popFront(a); })));
2390         static assert(!is(typeof({ typeof(S.init[0])[4] a; popFront(a); })));
2391     }}
2392 
2393     C[] _eatString(C)(C[] str)
2394     {
2395         while (!str.empty)
2396             str.popFront();
2397 
2398         return str;
2399     }
2400     enum checkCTFE = _eatString("ウェブサイト@La_Verité.com");
2401     static assert(checkCTFE.empty);
2402     enum checkCTFEW = _eatString("ウェブサイト@La_Verité.com"w);
2403     static assert(checkCTFEW.empty);
2404 }
2405 
2406 // https://issues.dlang.org/show_bug.cgi?id=16090
2407 @safe unittest
2408 {
2409     string s = "\u00E4";
2410     assert(s.length == 2);
2411     s = s[0 .. 1];
2412     assert(s.length == 1);
2413     s.popFront;
2414     assert(s.empty);
2415 }
2416 
2417 @safe unittest
2418 {
2419     wstring s = "\U00010000";
2420     assert(s.length == 2);
2421     s = s[0 .. 1];
2422     assert(s.length == 1);
2423     s.popFront;
2424     assert(s.empty);
2425 }
2426 
2427 /**
2428 Implements the range interface primitive `popBack` for built-in
2429 arrays. Due to the fact that nonmember functions can be called with
2430 the first argument using the dot notation, `array.popBack` is
2431 equivalent to `popBack(array)`. For $(GLOSSARY narrow strings), $(D
2432 popFront) automatically eliminates the last $(GLOSSARY code point).
2433 */
2434 void popBack(T)(scope ref inout(T)[] a) @safe pure nothrow @nogc
2435 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2436 {
2437     assert(a.length);
2438     a = a[0 .. $ - 1];
2439 }
2440 
2441 ///
2442 @safe pure nothrow unittest
2443 {
2444     auto a = [ 1, 2, 3 ];
2445     a.popBack();
2446     assert(a == [ 1, 2 ]);
2447 }
2448 
2449 @safe unittest
2450 {
2451     static assert(!is(typeof({ immutable int[] a; popBack(a); })));
2452     static assert(!is(typeof({          int[4] a; popBack(a); })));
2453     static assert(!is(typeof({          void[] a; popBack(a); })));
2454 }
2455 
2456 /// ditto
2457 void popBack(T)(scope ref inout(T)[] a) @safe pure
2458 if (isAutodecodableString!(T[]))
2459 {
2460     import std.utf : strideBack;
2461     assert(a.length, "Attempting to popBack() past the front of an array of " ~ T.stringof);
2462     a = a[0 .. $ - strideBack(a, $)];
2463 }
2464 
2465 @safe pure unittest
2466 {
2467     import std.meta : AliasSeq;
2468 
2469     static foreach (S; AliasSeq!(string, wstring, dstring))
2470     {{
2471         S s = "hello\xE2\x89\xA0";
2472         s.popBack();
2473         assert(s == "hello");
2474         S s3 = "\xE2\x89\xA0";
2475         auto c = s3.back;
2476         assert(c == cast(dchar)'\u2260');
2477         s3.popBack();
2478         assert(s3 == "");
2479 
2480         S str = "\U00010143\u0100\U00010143hello";
2481         foreach (dchar ch; ['o', 'l', 'l', 'e', 'h', '\U00010143', '\u0100', '\U00010143'])
2482         {
2483             assert(str.back == ch);
2484             str.popBack();
2485         }
2486         assert(str.empty);
2487 
2488         static assert(!is(typeof({          immutable S a; popBack(a); })));
2489         static assert(!is(typeof({ typeof(S.init[0])[4] a; popBack(a); })));
2490     }}
2491 }
2492 
2493 /**
2494 EXPERIMENTAL: to try out removing autodecoding, set the version
2495 `NoAutodecodeStrings`. Most things are expected to fail with this version
2496 currently.
2497 */
2498 version (NoAutodecodeStrings)
2499 {
2500     enum autodecodeStrings = false;
2501 }
2502 else
2503 {
2504     ///
2505     enum autodecodeStrings = true;
2506 }
2507 
2508 /**
2509 Implements the range interface primitive `front` for built-in
2510 arrays. Due to the fact that nonmember functions can be called with
2511 the first argument using the dot notation, `array.front` is
2512 equivalent to `front(array)`. For $(GLOSSARY narrow strings), $(D
2513 front) automatically returns the first $(GLOSSARY code point) as _a $(D
2514 dchar).
2515 */
2516 @property ref inout(T) front(T)(return scope inout(T)[] a) @safe pure nothrow @nogc
2517 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2518 {
2519     assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof);
2520     return a[0];
2521 }
2522 
2523 ///
2524 @safe pure nothrow unittest
2525 {
2526     int[] a = [ 1, 2, 3 ];
2527     assert(a.front == 1);
2528 }
2529 
2530 @safe pure nothrow unittest
2531 {
2532     auto a = [ 1, 2 ];
2533     a.front = 4;
2534     assert(a.front == 4);
2535     assert(a == [ 4, 2 ]);
2536 
2537     immutable b = [ 1, 2 ];
2538     assert(b.front == 1);
2539 
2540     int[2] c = [ 1, 2 ];
2541     assert(c.front == 1);
2542 }
2543 
2544 /// ditto
2545 @property dchar front(T)(scope const(T)[] a) @safe pure
2546 if (isAutodecodableString!(T[]))
2547 {
2548     import std.utf : decode;
2549     assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof);
2550     size_t i = 0;
2551     return decode(a, i);
2552 }
2553 
2554 /**
2555 Implements the range interface primitive `back` for built-in
2556 arrays. Due to the fact that nonmember functions can be called with
2557 the first argument using the dot notation, `array.back` is
2558 equivalent to `back(array)`. For $(GLOSSARY narrow strings), $(D
2559 back) automatically returns the last $(GLOSSARY code point) as _a $(D
2560 dchar).
2561 */
2562 @property ref inout(T) back(T)(return scope inout(T)[] a) @safe pure nothrow @nogc
2563 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2564 {
2565     assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof);
2566     return a[$ - 1];
2567 }
2568 
2569 ///
2570 @safe pure nothrow unittest
2571 {
2572     int[] a = [ 1, 2, 3 ];
2573     assert(a.back == 3);
2574     a.back += 4;
2575     assert(a.back == 7);
2576 }
2577 
2578 @safe pure nothrow unittest
2579 {
2580     immutable b = [ 1, 2, 3 ];
2581     assert(b.back == 3);
2582 
2583     int[3] c = [ 1, 2, 3 ];
2584     assert(c.back == 3);
2585 }
2586 
2587 /// ditto
2588 // Specialization for strings
2589 @property dchar back(T)(scope const(T)[] a) @safe pure
2590 if (isAutodecodableString!(T[]))
2591 {
2592     import std.utf : decode, strideBack;
2593     assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof);
2594     size_t i = a.length - strideBack(a, a.length);
2595     return decode(a, i);
2596 }
2597 
2598 /*
2599 Implements `length` for a range by forwarding it to `member`.
2600 */
2601 package(std) mixin template ImplementLength(alias member)
2602 {
2603     static if (hasLength!(typeof(member)))
2604     {
2605         @property auto length()
2606         {
2607             return member.length;
2608         }
2609         alias opDollar = length;
2610     }
2611 }
2612 
2613 @safe unittest
2614 {
2615     import std.meta : AliasSeq;
2616 
2617     foreach (alias E; AliasSeq!(noreturn, const(noreturn), immutable(noreturn) ))
2618     {
2619         alias R = E[];
2620 
2621         static assert(isInputRange!R);
2622         static assert(isForwardRange!R);
2623         static assert(isBidirectionalRange!R);
2624         static assert(isRandomAccessRange!R);
2625     }
2626 
2627     static assert(isOutputRange!(noreturn[], noreturn));
2628 }