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