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