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