d: Merge dmd. druntime e770945277, phobos 6d6e0b9b9
[official-gcc.git] / libphobos / src / std / range / primitives.d
blobdddcae9afd2ecde76e985d841d57b9156658c3b9
1 /**
2 This module is a submodule of $(MREF std, range).
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).
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:
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`.
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.
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.
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`.
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`.
41 It also provides number of templates that test for various range capabilities:
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`.
48 $(TR $(TD $(LREF ElementType))
49 $(TD Returns the element type of a given range.
51 $(TR $(TD $(LREF ElementEncodingType))
52 $(TD Returns the encoding element type of a given range.
54 $(TR $(TD $(LREF hasSwappableElements))
55 $(TD Tests if a range is a forward range with swappable elements.
57 $(TR $(TD $(LREF hasAssignableElements))
58 $(TD Tests if a range is a forward range with mutable elements.
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.
64 $(TR $(TD $(LREF hasLength))
65 $(TD Tests if a given range has the `length` attribute.
67 $(TR $(TD $(LREF isInfinite))
68 $(TD Tests if a given range is an $(I infinite range).
70 $(TR $(TD $(LREF hasSlicing))
71 $(TD Tests if a given range supports the array slicing operation $(D
72 R[x .. y]).
76 Finally, it includes some convenience functions for manipulating ranges:
78 $(BOOKTABLE ,
79 $(TR $(TD $(LREF popFrontN))
80 $(TD Advances a given range by up to $(I n) elements.
82 $(TR $(TD $(LREF popBackN))
83 $(TD Advances a given bidirectional range from the right by up to
84 $(I n) elements.
86 $(TR $(TD $(LREF popFrontExactly))
87 $(TD Advances a given range by up exactly $(I n) elements.
89 $(TR $(TD $(LREF popBackExactly))
90 $(TD Advances a given bidirectional range from the right by exactly
91 $(I n) elements.
93 $(TR $(TD $(LREF moveFront))
94 $(TD Removes the front element of a range.
96 $(TR $(TD $(LREF moveBack))
97 $(TD Removes the back element of a bidirectional range.
99 $(TR $(TD $(LREF moveAt))
100 $(TD Removes the $(I i)'th element of a random-access range.
102 $(TR $(TD $(LREF walkLength))
103 $(TD Computes the length of any range in O(n) time.
105 $(TR $(TD $(LREF put))
106 $(TD Outputs element `e` to a range.
110 Source: $(PHOBOSSRC std/range/primitives.d)
112 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
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).
119 module std.range.primitives;
121 import std.traits;
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.
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 ----
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.
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`.)
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.
163 See_Also:
164 The header of $(MREF std,range) for tutorials on ranges.
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
172 Returns:
173 `true` if R is an input range (possibly with element type `E`), `false` if not
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));
182 /// ditto
183 enum bool isInputRange(R, E) =
184 .isInputRange!R && isQualifierConvertible!(ElementType!R, E);
187 @safe unittest
189 struct A {}
190 struct B
192 void popFront();
193 @property bool empty();
194 @property int front();
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));
207 static assert(!isInputRange!(const(int)[], int));
208 static assert( isInputRange!(const(int)[], const int));
209 static assert(!isInputRange!(const(int)[], immutable int));
211 static assert(!isInputRange!(immutable(int)[], int));
212 static assert( isInputRange!(immutable(int)[], const int));
213 static assert( isInputRange!(immutable(int)[], immutable int));
215 static struct NotDefaultConstructible
217 @disable this();
218 void popFront();
219 @property bool empty();
220 @property int front();
222 static assert( isInputRange!NotDefaultConstructible);
224 static struct NotDefaultConstructibleOrCopyable
226 @disable this();
227 @disable this(this);
228 void popFront();
229 @property bool empty();
230 @property int front();
232 static assert(isInputRange!NotDefaultConstructibleOrCopyable);
234 static struct Frontless
236 void popFront();
237 @property bool empty();
239 static assert(!isInputRange!Frontless);
241 static struct VoidFront
243 void popFront();
244 @property bool empty();
245 void front();
247 static assert(!isInputRange!VoidFront);
249 // https://issues.dlang.org/show_bug.cgi?id=16034
250 @safe unittest
252 struct One
254 int entry = 1;
255 @disable this(this);
258 assert(isInputRange!(One[]));
261 @safe unittest
263 import std.algorithm.comparison : equal;
265 static struct R
267 static struct Front
269 R* impl;
270 @property int value() { return impl._front; }
271 alias value this;
274 int _front;
276 @property bool empty() { return _front >= 3; }
277 @property auto front() { return Front(&this); }
278 void popFront() { _front++; }
280 R r;
282 static assert(isInputRange!R);
283 assert(r.equal([ 0, 1, 2 ]));
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.
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.
296 private void doPut(R, E)(ref R r, auto ref E e)
298 static if (is(PointerTarget!R == struct))
299 enum usingPut = hasMember!(PointerTarget!R, "put");
300 else
301 enum usingPut = hasMember!(R, "put");
303 static if (usingPut)
305 static assert(is(typeof(r.put(e))),
306 "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ ".");
307 r.put(e);
309 else static if (isNarrowString!R && is(const(E) == const(typeof(r[0]))))
311 // one character, we can put it
312 r[0] = e;
313 r = r[1 .. $];
315 else static if (isNarrowString!R && isNarrowString!E && is(typeof(r[] = e)))
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 .. $];
323 else static if (isInputRange!R)
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();
330 else static if (is(typeof(r(e))))
332 r(e);
334 else
336 static assert(false,
337 "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ ".");
341 @safe unittest
343 static assert(!isNativeOutputRange!(int, int));
344 static assert( isNativeOutputRange!(int[], int));
345 static assert(!isNativeOutputRange!(int[][], int));
347 static assert(!isNativeOutputRange!(int, int[]));
348 static assert(!isNativeOutputRange!(int[], int[]));
349 static assert( isNativeOutputRange!(int[][], int[]));
351 static assert(!isNativeOutputRange!(int, int[][]));
352 static assert(!isNativeOutputRange!(int[], int[][]));
353 static assert(!isNativeOutputRange!(int[][], int[][]));
355 static assert(!isNativeOutputRange!(int[4], int));
356 static assert( isNativeOutputRange!(int[4][], int)); //Scary!
357 static assert( isNativeOutputRange!(int[4][], int[4]));
359 static assert( isNativeOutputRange!( char[], char));
360 static assert(!isNativeOutputRange!( char[], dchar));
361 static assert( isNativeOutputRange!(dchar[], char));
362 static assert( isNativeOutputRange!(dchar[], dchar));
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.
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.
377 $(BOOKTABLE ,
378 $(TR
379 $(TH Code Snippet)
380 $(TH Scenario)
382 $(TR
383 $(TD `r.doPut(e);`)
384 $(TD `R` specifically accepts an `E`.)
386 $(TR
387 $(TD $(D r.doPut([ e ]);))
388 $(TD `R` specifically accepts an `E[]`.)
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.)
395 $(TR
396 $(TD $(D for (; !e.empty; e.popFront()) put(r, e.front);))
397 $(TD Copying range `E` into `R`.)
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.
405 void put(R, E)(ref R r, E e)
407 //First level: simply straight up put.
408 static if (is(typeof(doPut(r, e))))
410 doPut(r, e);
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[])))
418 immutable len = e.length;
419 r[0 .. len] = e[];
420 r = r[len .. $];
422 //Accepts E[] ?
423 else static if (is(typeof(doPut(r, [e]))) && !isDynamicArray!R)
425 if (__ctfe)
427 E[1] arr = [e];
428 doPut(r, arr[]);
430 else
431 doPut(r, (ref e) @trusted { return (&e)[0 .. 1]; }(e));
433 //special case for char to string.
434 else static if (isSomeChar!E && is(typeof(putChar(r, e))))
436 putChar(r, e);
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))))
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)))) ) )
449 foreach (c; e)
450 doPut(r, c);
452 else
454 for (; !e.empty; e.popFront())
455 put(r, e.front);
458 else
460 static assert(false, "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ ".");
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.
469 @safe pure unittest
471 import std.traits : isSomeChar;
473 static struct A
475 string data;
477 void put(C)(C c) if (isSomeChar!C)
479 data ~= c;
482 static assert(isOutputRange!(A, char));
484 auto a = A();
485 put(a, "Hello");
486 assert(a.data == "Hello");
490 * `put` treats dynamic arrays as array slices, and will call `popFront`
491 * on the slice after an element has been copied.
493 * Be sure to save the position of the array before calling `put`.
495 @safe pure nothrow unittest
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]);
507 * It's also possible to `put` any width strings or characters into narrow
508 * strings -- put does the conversion for you.
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).
513 @safe pure unittest
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!");
523 @safe pure nothrow unittest
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!");
533 @safe pure nothrow @nogc unittest
535 static struct R() { void put(scope const(char)[]) {} }
536 R!() r;
537 put(r, 'a');
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)
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(); }())));
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)));
555 //Fast transform a narrow char into a wider string
556 static if ((wsCond && E.sizeof < wchar.sizeof) || (dsCond && E.sizeof < dchar.sizeof))
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[]);
563 //Encode a wide char into a narrower string
564 else static if (wsCond || csCond)
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)]);
570 //Slowly encode a wide char into a series of narrower chars
571 else static if (wcCond || ccCond)
573 import std.encoding : encode;
574 alias C = Select!(wcCond, wchar, char);
575 encode!(C, R)(e, r);
577 else
579 static assert(false, "Cannot put a " ~ E.stringof ~ " into a " ~ R.stringof ~ ".");
583 pure @safe unittest
585 auto f = delegate (const(char)[]) {};
586 putChar(f, cast(dchar)'a');
590 @safe pure unittest
592 static struct R() { void put(scope const(char)[]) {} }
593 R!() r;
594 putChar(r, 'a');
597 @safe unittest
599 struct A {}
600 static assert(!isInputRange!(A));
601 struct B
603 void put(int) {}
605 B b;
606 put(b, 5);
609 @safe unittest
611 int[] a = new int[10];
612 int b;
613 static assert(isInputRange!(typeof(a)));
614 put(a, b);
617 @safe unittest
619 void myprint(scope const(char)[] s) { }
620 auto r = &myprint;
621 put(r, 'a');
624 @safe unittest
626 int[] a = new int[10];
627 static assert(!__traits(compiles, put(a, 1.0L)));
628 put(a, 1);
629 assert(a.length == 9);
631 * a[0] = 65; // OK
632 * a[0] = 'A'; // OK
633 * a[0] = "ABC"[0]; // OK
634 * put(a, "ABC"); // OK
636 put(a, "ABC");
637 assert(a.length == 6);
640 @safe unittest
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)));
654 @safe unittest
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);
663 a = b; // reset
664 put(a, 'λ');
665 assert(b[0 .. 2] == "λ");
666 assert(a.length == 8);
668 a = b; // reset
669 put(a, "ABC"d);
670 assert(b[0 .. 3] == "ABC");
671 assert(a.length == 7);
673 a = b; // reset
674 put(a, '𐐷');
675 assert(b[0 .. 4] == "𐐷");
676 assert(a.length == 6);
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);
684 aw = bw; // reset
685 put(aw, 'λ');
686 assert(bw[0 .. 1] == "λ"w);
687 assert(aw.length == 9);
689 aw = bw; // reset
690 put(aw, "ABC"d);
691 assert(bw[0 .. 3] == "ABC"w);
692 assert(aw.length == 7);
694 aw = bw; // reset
695 put(aw, '𐐷');
696 assert(bw[0 .. 2] == "𐐷"w);
697 assert(aw.length == 8);
699 aw = bw; // reset
700 put(aw, "𐐷"); // try transcoding from char[]
701 assert(bw[0 .. 2] == "𐐷"w);
702 assert(aw.length == 8);
705 @safe unittest
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)));
717 @safe unittest
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]]);
732 @safe unittest
734 // Test fix for bug 7476.
735 struct LockingTextWriter
737 void put(dchar c){}
739 struct RetroResult
741 bool end = false;
742 @property bool empty() const { return end; }
743 @property dchar front(){ return 'a'; }
744 void popFront(){ end = true; }
746 LockingTextWriter w;
747 RetroResult re;
748 put(w, re);
751 @system unittest
753 import std.conv : to;
754 import std.meta : AliasSeq;
755 import std.typecons : tuple;
757 static struct PutC(C)
759 string result;
760 void put(const(C) c) { result ~= to!string((&c)[0 .. 1]); }
762 static struct PutS(C)
764 string result;
765 void put(const(C)[] s) { result ~= to!string(s); }
767 static struct PutSS(C)
769 string result;
770 void put(const(C)[][] ss)
772 foreach (s; ss)
773 result ~= to!string(s);
777 PutS!char p;
778 putChar(p, cast(dchar)'a');
780 //Source Char
781 static foreach (SC; AliasSeq!(char, wchar, dchar))
783 SC ch = 'I';
784 dchar dh = '♥';
785 immutable(SC)[] s = "日本語!";
786 immutable(SC)[][] ss = ["日本語", "が", "好き", "ですか", "?"];
788 //Target Char
789 static foreach (TC; AliasSeq!(char, wchar, dchar))
791 //Testing PutC and PutS
792 static foreach (Type; AliasSeq!(PutC!TC, PutS!TC))
794 Type type;
795 auto sink = new Type();
797 //Testing put and sink
798 foreach (value ; tuple(type, sink))
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♥日本語!日本語が好きですか?");
814 @safe unittest
816 static struct CharRange
818 char c;
819 enum empty = false;
820 void popFront(){}
821 ref char front() return @property
823 return c;
826 CharRange c;
827 put(c, cast(dchar)'H');
828 put(c, "hello"d);
831 // https://issues.dlang.org/show_bug.cgi?id=9823
832 @system unittest
834 const(char)[] r;
835 void delegate(const(char)[]) dg = (s) { r = s; };
836 put(dg, ["ABC"]);
837 assert(r == "ABC");
840 // https://issues.dlang.org/show_bug.cgi?id=10571
841 @safe unittest
843 import std.format.write : formattedWrite;
844 string buf;
845 formattedWrite((scope const(char)[] s) { buf ~= s; }, "%s", "hello");
846 assert(buf == "hello");
849 @safe unittest
851 import std.format.write : formattedWrite;
852 import std.meta : AliasSeq;
853 struct PutC(C)
855 void put(C){}
857 struct PutS(C)
859 void put(const(C)[]){}
861 struct CallC(C)
863 void opCall(C){}
865 struct CallS(C)
867 void opCall(const(C)[]){}
869 struct FrontC(C)
871 enum empty = false;
872 auto front()@property{return C.init;}
873 void front(C)@property{}
874 void popFront(){}
876 struct FrontS(C)
878 enum empty = false;
879 auto front()@property{return C[].init;}
880 void front(const(C)[])@property{}
881 void popFront(){}
883 void foo()
885 static foreach (C; AliasSeq!(char, wchar, dchar))
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);
898 formattedWrite((dchar[]).init, "", 1, 'a', cast(wchar)'a', cast(dchar)'a', "a"c, "a"w, "a"d);
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.
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.
914 package(std) enum bool isNativeOutputRange(R, E) =
915 is(typeof(doPut(lvalueOf!R, lvalueOf!E)));
917 @safe unittest
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[]));
925 if (!r.empty)
926 put(r, 1); //guaranteed to succeed
927 if (!r.empty)
928 put(r, [1, 2]); //May actually error out.
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.
936 See_Also:
937 The header of $(MREF std,range) for tutorials on ranges.
939 enum bool isOutputRange(R, E) =
940 is(typeof(put(lvalueOf!R, lvalueOf!E)));
943 @safe unittest
945 void myprint(scope const(char)[] s) { }
946 static assert(isOutputRange!(typeof(&myprint), char));
948 static assert( isOutputRange!(char[], char));
949 static assert( isOutputRange!(dchar[], wchar));
950 static assert( isOutputRange!(dchar[], dchar));
953 @safe unittest
955 import std.array;
956 import std.stdio : writeln;
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));
969 static assert(!isOutputRange!(const(int)[], int));
970 static assert(!isOutputRange!(inout(int)[], int));
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.
984 The following code should compile for any forward range.
986 ----
987 static assert(isInputRange!R);
988 R r1;
989 auto s1 = r1.save;
990 static assert(is(typeof(s1) == R));
991 ----
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.
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.
1002 `save` behaves in many ways like a copy constructor, and its
1003 implementation typically is done using copy construction.
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.
1012 See_Also:
1013 The header of $(MREF std,range) for tutorials on ranges.
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
1021 Returns:
1022 `true` if R is a forward range (possibly with element type `E`), `false` if not
1024 enum bool isForwardRange(R) = isInputRange!R
1025 && is(typeof((R r) { return r.save; } (R.init)) == R);
1027 /// ditto
1028 enum bool isForwardRange(R, E) =
1029 .isForwardRange!R && isQualifierConvertible!(ElementType!R, E);
1032 @safe unittest
1034 static assert(!isForwardRange!(int));
1035 static assert( isForwardRange!(int[]));
1036 static assert( isForwardRange!(inout(int)[]));
1038 static assert( isForwardRange!(int[], const int));
1039 static assert(!isForwardRange!(int[], immutable int));
1041 static assert(!isForwardRange!(const(int)[], int));
1042 static assert( isForwardRange!(const(int)[], const int));
1043 static assert(!isForwardRange!(const(int)[], immutable int));
1045 static assert(!isForwardRange!(immutable(int)[], int));
1046 static assert( isForwardRange!(immutable(int)[], const int));
1047 static assert( isForwardRange!(immutable(int)[], immutable int));
1050 @safe unittest
1052 // BUG 14544
1053 struct R14544
1055 int front() { return 0;}
1056 void popFront() {}
1057 bool empty() { return false; }
1058 R14544 save() {return this;}
1061 static assert( isForwardRange!R14544 );
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.
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`):
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`.))
1078 See_Also:
1079 The header of $(MREF std,range) for tutorials on ranges.
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
1087 Returns:
1088 `true` if R is a bidirectional range (possibly with element type `E`), `false` if not
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);
1095 /// ditto
1096 enum bool isBidirectionalRange(R, E) =
1097 .isBidirectionalRange!R && isQualifierConvertible!(ElementType!R, E);
1100 @safe unittest
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
1110 // Checking the element type
1111 static assert( isBidirectionalRange!(int[], const int));
1112 static assert(!isBidirectionalRange!(int[], immutable int));
1114 static assert(!isBidirectionalRange!(const(int)[], int));
1115 static assert( isBidirectionalRange!(const(int)[], const int));
1116 static assert(!isBidirectionalRange!(const(int)[], immutable int));
1118 static assert(!isBidirectionalRange!(immutable(int)[], int));
1119 static assert( isBidirectionalRange!(immutable(int)[], const int));
1120 static assert( isBidirectionalRange!(immutable(int)[], immutable int));
1123 @safe unittest
1125 struct A {}
1126 struct B
1128 void popFront();
1129 @property bool empty();
1130 @property int front();
1132 struct C
1134 @property bool empty();
1135 @property C save();
1136 void popFront();
1137 @property int front();
1138 void popBack();
1139 @property int back();
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)[]));
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.
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.))
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.
1168 See_Also:
1169 The header of $(MREF std,range) for tutorials on ranges.
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
1177 Returns:
1178 `true` if R is a random-access range (possibly with element type `E`), `false` if not
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));
1189 /// ditto
1190 enum bool isRandomAccessRange(R, E) =
1191 .isRandomAccessRange!R && isQualifierConvertible!(ElementType!R, E);
1194 @safe unittest
1196 import std.traits : isAggregateType, isAutodecodableString;
1198 alias R = int[];
1200 // range is finite and bidirectional or infinite and forward.
1201 static assert(isBidirectionalRange!R ||
1202 isForwardRange!R && isInfinite!R);
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
1211 // $ must work as it does with arrays if opIndex works with $
1212 static if (is(typeof(r[$])))
1214 static assert(is(typeof(f) == typeof(r[$])));
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])));
1222 // Checking the element type
1223 static assert( isRandomAccessRange!(int[], const int));
1224 static assert(!isRandomAccessRange!(int[], immutable int));
1226 static assert(!isRandomAccessRange!(const(int)[], int));
1227 static assert( isRandomAccessRange!(const(int)[], const int));
1228 static assert(!isRandomAccessRange!(const(int)[], immutable int));
1230 static assert(!isRandomAccessRange!(immutable(int)[], int));
1231 static assert( isRandomAccessRange!(immutable(int)[], const int));
1232 static assert( isRandomAccessRange!(immutable(int)[], immutable int));
1235 @safe unittest
1237 struct A {}
1238 struct B
1240 void popFront();
1241 @property bool empty();
1242 @property int front();
1244 struct C
1246 void popFront();
1247 @property bool empty();
1248 @property int front();
1249 void popBack();
1250 @property int back();
1252 struct D
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);
1265 struct E
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);
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)[]));
1287 @safe unittest
1289 // Test fix for bug 6935.
1290 struct R
1292 @disable this();
1294 @property bool empty() const { return false; }
1295 @property int front() const { return 0; }
1296 void popFront() {}
1298 @property R save() { return this; }
1300 @property int back() const { return 0; }
1301 void popBack(){}
1303 int opIndex(size_t n) const { return 0; }
1304 @property size_t length() const { return 0; }
1305 alias opDollar = length;
1307 void put(int e){ }
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));
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.
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 ----
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));
1344 @safe unittest
1346 import std.algorithm.iteration : map;
1347 import std.range : iota, repeat;
1349 static struct HasPostblit
1351 this(this) {}
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))));
1360 static assert( hasMobileElements!( string));
1361 static assert( hasMobileElements!(dstring));
1362 static assert( hasMobileElements!( char[]));
1363 static assert( hasMobileElements!(dchar[]));
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`.
1374 template ElementType(R)
1376 static if (is(typeof(R.init.front.init) T))
1377 alias ElementType = T;
1378 else
1379 alias ElementType = void;
1383 @safe unittest
1385 import std.range : iota;
1387 // Standard arrays: returns the type of the elements of the array
1388 static assert(is(ElementType!(int[]) == int));
1390 // Accessing .front retrieves the decoded dchar
1391 static assert(is(ElementType!(char[]) == dchar)); // rvalue
1392 static assert(is(ElementType!(dchar[]) == dchar)); // lvalue
1394 // Ditto
1395 static assert(is(ElementType!(string) == dchar));
1396 static assert(is(ElementType!(dstring) == immutable(dchar)));
1398 // For ranges it gets the type of .front.
1399 auto range = iota(0, 10);
1400 static assert(is(ElementType!(typeof(range)) == int));
1403 @safe unittest
1405 static assert(is(ElementType!(byte[]) == byte));
1406 static assert(is(ElementType!(wchar[]) == dchar)); // rvalue
1407 static assert(is(ElementType!(wstring) == dchar));
1410 @safe unittest
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)));
1425 @safe unittest
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));
1433 // https://issues.dlang.org/show_bug.cgi?id=11336
1434 @safe unittest
1436 static struct S
1438 this(this) @disable;
1440 static assert(is(ElementType!(S[]) == S));
1443 // https://issues.dlang.org/show_bug.cgi?id=11401
1444 @safe unittest
1446 // ElementType should also work for non-@propety 'front'
1447 struct E { ushort id; }
1448 struct R
1450 E front() { return E.init; }
1452 static assert(is(ElementType!R == E));
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`.
1462 template ElementEncodingType(R)
1464 static if (is(StringTypeOf!R) && is(R : E[], E))
1465 alias ElementEncodingType = E;
1466 else
1467 alias ElementEncodingType = ElementType!R;
1471 @safe unittest
1473 import std.range : iota;
1474 // internally the range stores the encoded type
1475 static assert(is(ElementEncodingType!(char[]) == char));
1477 static assert(is(ElementEncodingType!(wstring) == immutable(wchar)));
1479 static assert(is(ElementEncodingType!(byte[]) == byte));
1481 auto range = iota(0, 10);
1482 static assert(is(ElementEncodingType!(typeof(range)) == int));
1485 @safe unittest
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));
1494 @safe unittest
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));
1509 static assert(is(ElementEncodingType!(inout char[]) : inout(char)));
1512 @safe unittest
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));
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.
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 ----
1533 template hasSwappableElements(R)
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))));
1545 @safe unittest
1547 static assert(!hasSwappableElements!(const int[]));
1548 static assert(!hasSwappableElements!(const(int)[]));
1549 static assert(!hasSwappableElements!(inout(int)[]));
1550 static assert( hasSwappableElements!(int[]));
1552 static assert(!hasSwappableElements!( string));
1553 static assert(!hasSwappableElements!(dstring));
1554 static assert(!hasSwappableElements!( char[]));
1555 static assert( hasSwappableElements!(dchar[]));
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.
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 ----
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)));
1579 @safe unittest
1581 static assert(!hasAssignableElements!(const int[]));
1582 static assert(!hasAssignableElements!(const(int)[]));
1583 static assert( hasAssignableElements!(int[]));
1584 static assert(!hasAssignableElements!(inout(int)[]));
1586 static assert(!hasAssignableElements!( string));
1587 static assert(!hasAssignableElements!(dstring));
1588 static assert(!hasAssignableElements!( char[]));
1589 static assert( hasAssignableElements!(dchar[]));
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);
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 ----
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]))));
1612 /* Compile successfully if argument of type T is an lvalue
1614 private void isLvalue(T)(T)
1615 if (0);
1617 private void isLvalue(T)(ref T)
1618 if (1);
1621 @safe unittest
1623 import std.range : iota, chain;
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))));
1631 static assert(!hasLvalueElements!( string));
1632 static assert( hasLvalueElements!(dstring));
1633 static assert(!hasLvalueElements!( char[]));
1634 static assert( hasLvalueElements!(dchar[]));
1636 auto c = chain([1, 2, 3], [4, 5, 6]);
1637 static assert( hasLvalueElements!(typeof(c)));
1640 @safe unittest
1642 // bugfix 6336
1643 struct S { immutable int value; }
1644 static assert( isInputRange!(S[]));
1645 static assert( hasLvalueElements!(S[]));
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`.
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.
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).
1665 template hasLength(R)
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;
1675 @safe unittest
1677 static assert(!hasLength!(char[]));
1678 static assert( hasLength!(int[]));
1679 static assert( hasLength!(inout(int)[]));
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));
1687 // test combinations which are invalid on some platforms
1688 @safe unittest
1690 struct A { ulong length; }
1691 struct B { @property uint length() { return 0; } }
1693 static if (is(size_t == uint))
1695 static assert(!hasLength!(A));
1696 static assert(hasLength!(B));
1698 else static if (is(size_t == ulong))
1700 static assert(hasLength!(A));
1701 static assert(!hasLength!(B));
1705 // test combinations which are invalid on all platforms
1706 @safe unittest
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));
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:
1724 ----
1725 struct MyInfiniteRange
1727 enum bool empty = false;
1730 ----
1733 template isInfinite(R)
1735 static if (isInputRange!R && __traits(compiles, { enum e = R.empty; }))
1736 enum bool isInfinite = !R.empty;
1737 else
1738 enum bool isInfinite = false;
1742 @safe unittest
1744 import std.range : Repeat;
1745 static assert(!isInfinite!(int[]));
1746 static assert( isInfinite!(Repeat!(int)));
1750 Returns `true` if `R` offers a slicing operator with integral boundaries
1751 that returns a forward range type.
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.
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.
1761 The following expression must be true for `hasSlicing` to be `true`:
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)
1773 static assert(isForwardRange!(typeof(r[1 .. 2])));
1774 }));
1775 ----
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)
1786 static assert(isForwardRange!(typeof(r[1 .. 2])));
1787 }));
1790 @safe unittest
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);
1803 enum rangeFuncs = "@property int front();" ~
1804 "void popFront();" ~
1805 "@property bool empty();" ~
1806 "@property auto save() { return this; }" ~
1807 "@property size_t length();";
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));
1818 struct InfOnes
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; }
1827 struct Dollar {}
1828 Dollar opDollar() const { return Dollar.init; }
1831 static assert(hasSlicing!InfOnes);
1834 // https://issues.dlang.org/show_bug.cgi?id=24348
1835 @safe unittest
1837 static struct Slice
1839 size_t length;
1840 bool empty() => length == 0;
1841 int front() => 0;
1842 void popFront() { --length; }
1843 Slice save() => this;
1846 static struct InfZeros
1848 enum empty = false;
1849 int front() => 0;
1850 void popFront() {}
1851 InfZeros save() => this;
1853 Slice opIndex(size_t[2] bounds)
1855 size_t i = bounds[0], j = bounds[1];
1856 size_t length = i <= j ? j - i : 0;
1857 return Slice(length);
1860 size_t[2] opSlice(size_t dim : 0)(size_t i, size_t j) => [i, j];
1863 static assert(hasSlicing!InfZeros);
1867 This is a best-effort implementation of `length` for any kind of
1868 range.
1870 If `hasLength!Range`, simply returns `range.length` without
1871 checking `upTo` (when specified).
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).
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`.
1883 Infinite ranges are compatible, provided the parameter `upTo` is
1884 specified, in which case the implementation simply returns upTo.
1886 auto walkLength(Range)(Range range)
1887 if (isInputRange!Range && !isInfinite!Range)
1889 static if (hasLength!Range)
1890 return range.length;
1891 else
1893 size_t result;
1894 static if (autodecodeStrings && isNarrowString!Range)
1896 import std.utf : codeUnitLimit;
1897 result = range.length;
1898 foreach (const i, const c; range)
1900 if (c >= codeUnitLimit!Range)
1902 result = i;
1903 break;
1906 range = range[result .. $];
1908 for ( ; !range.empty ; range.popFront() )
1909 ++result;
1910 return result;
1913 /// ditto
1914 auto walkLength(Range)(Range range, const size_t upTo)
1915 if (isInputRange!Range)
1917 static if (hasLength!Range)
1918 return range.length;
1919 else static if (isInfinite!Range)
1920 return upTo;
1921 else
1923 size_t result;
1924 static if (autodecodeStrings && isNarrowString!Range)
1926 import std.utf : codeUnitLimit;
1927 result = upTo > range.length ? range.length : upTo;
1928 foreach (const i, const c; range[0 .. result])
1930 if (c >= codeUnitLimit!Range)
1932 result = i;
1933 break;
1936 range = range[result .. $];
1938 for ( ; result < upTo && !range.empty ; range.popFront() )
1939 ++result;
1940 return result;
1945 @safe unittest
1947 import std.range : iota;
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);
1956 @safe unittest
1958 import std.algorithm.iteration : filter;
1959 import std.range : recurrence, take;
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);
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);
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);
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.
1990 `popBackN` behaves the same as `popFrontN` but instead removes
1991 elements from the back of the (bidirectional) range instead of the front.
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.
1997 See_Also: $(REF drop, std, range), $(REF dropBack, std, range)
1999 size_t popFrontN(Range)(ref Range r, size_t n)
2000 if (isInputRange!Range)
2002 static if (hasLength!Range)
2004 n = cast(size_t) (n < r.length ? n : r.length);
2007 static if (hasSlicing!Range && is(typeof(r = r[n .. $])))
2009 r = r[n .. $];
2011 else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar.
2013 r = r[n .. r.length];
2015 else
2017 static if (hasLength!Range)
2019 foreach (i; 0 .. n)
2020 r.popFront();
2022 else
2024 foreach (i; 0 .. n)
2026 if (r.empty) return i;
2027 r.popFront();
2031 return n;
2034 /// ditto
2035 size_t popBackN(Range)(ref Range r, size_t n)
2036 if (isBidirectionalRange!Range)
2038 static if (hasLength!Range)
2040 n = cast(size_t) (n < r.length ? n : r.length);
2043 static if (hasSlicing!Range && is(typeof(r = r[0 .. $ - n])))
2045 r = r[0 .. $ - n];
2047 else static if (hasSlicing!Range && hasLength!Range) //TODO: Remove once hasSlicing forces opDollar.
2049 r = r[0 .. r.length - n];
2051 else
2053 static if (hasLength!Range)
2055 foreach (i; 0 .. n)
2056 r.popBack();
2058 else
2060 foreach (i; 0 .. n)
2062 if (r.empty) return i;
2063 r.popBack();
2067 return n;
2071 @safe unittest
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 == [ ]);
2081 @safe unittest
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);
2092 @safe unittest
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 == [ ]);
2102 @safe unittest
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);
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.
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.
2127 `popBackExactly` will behave the same but instead removes elements from
2128 the back of the (bidirectional) range instead of the front.
2130 See_Also: $(REF dropExactly, std, range), $(REF dropBackExactly, std, range)
2132 void popFrontExactly(Range)(ref Range r, size_t n)
2133 if (isInputRange!Range)
2135 static if (hasLength!Range)
2136 assert(n <= r.length, "range is smaller than amount of items to pop");
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();
2147 /// ditto
2148 void popBackExactly(Range)(ref Range r, size_t n)
2149 if (isBidirectionalRange!Range)
2151 static if (hasLength!Range)
2152 assert(n <= r.length, "range is smaller than amount of items to pop");
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();
2164 @safe unittest
2166 import std.algorithm.comparison : equal;
2167 import std.algorithm.iteration : filterBidirectional;
2169 auto a = [1, 2, 3];
2170 a.popFrontExactly(1);
2171 assert(a == [2, 3]);
2172 a.popBackExactly(1);
2173 assert(a == [2]);
2175 string s = "日本語";
2176 s.popFrontExactly(1);
2177 assert(s == "本語");
2178 s.popBackExactly(1);
2179 assert(s == "本");
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]));
2189 Moves the front of `r` out and returns it.
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.
2195 In either case, `r.front` is left in a destroyable state that does not
2196 allocate any resources.
2198 ElementType!R moveFront(R)(R r)
2200 static if (is(typeof(&r.moveFront)))
2202 return r.moveFront();
2204 else static if (!hasElaborateCopyConstructor!(ElementType!R))
2206 return r.front;
2208 else static if (is(typeof(&(r.front())) == ElementType!R*))
2210 import std.algorithm.mutation : move;
2211 return move(r.front);
2213 else
2215 static assert(0,
2216 "Cannot move front of a range with a postblit and an rvalue front.");
2221 @safe unittest
2223 auto a = [ 1, 2, 3 ];
2224 assert(moveFront(a) == 1);
2225 assert(a.length == 3);
2227 // define a perfunctory input range
2228 struct InputRange
2230 enum bool empty = false;
2231 enum int front = 7;
2232 void popFront() {}
2233 int moveFront() { return 43; }
2235 InputRange r;
2236 // calls r.moveFront
2237 assert(moveFront(r) == 43);
2240 @safe unittest
2242 struct R
2244 @property ref int front() { static int x = 42; return x; }
2245 this(this){}
2247 R r;
2248 assert(moveFront(r) == 42);
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).
2256 ElementType!R moveBack(R)(R r)
2258 static if (is(typeof(&r.moveBack)))
2260 return r.moveBack();
2262 else static if (!hasElaborateCopyConstructor!(ElementType!R))
2264 return r.back;
2266 else static if (is(typeof(&(r.back())) == ElementType!R*))
2268 import std.algorithm.mutation : move;
2269 return move(r.back);
2271 else
2273 static assert(0,
2274 "Cannot move back of a range with a postblit and an rvalue back.");
2279 @safe unittest
2281 struct TestRange
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() { }
2291 static assert(isBidirectionalRange!TestRange);
2292 TestRange r;
2293 auto x = moveBack(r);
2294 assert(x == 5);
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).
2302 ElementType!R moveAt(R)(R r, size_t i)
2304 static if (is(typeof(&r.moveAt)))
2306 return r.moveAt(i);
2308 else static if (!hasElaborateCopyConstructor!(ElementType!(R)))
2310 return r[i];
2312 else static if (is(typeof(&r[i]) == ElementType!R*))
2314 import std.algorithm.mutation : move;
2315 return move(r[i]);
2317 else
2319 static assert(0,
2320 "Cannot move element of a range with a postblit and rvalue elements.");
2325 @safe unittest
2327 auto a = [1,2,3,4];
2328 foreach (idx, it; a)
2330 assert(it == moveAt(a, idx));
2334 @safe unittest
2336 import std.internal.test.dummyrange;
2338 foreach (DummyType; AllDummyRanges)
2340 auto d = DummyType.init;
2341 assert(moveFront(d) == 1);
2343 static if (isBidirectionalRange!DummyType)
2345 assert(moveBack(d) == 10);
2348 static if (isRandomAccessRange!DummyType)
2350 assert(moveAt(d, 2) == 3);
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)`.
2361 @property bool empty(T)(auto ref scope T a)
2362 if (is(typeof(a.length) : size_t))
2364 return !a.length;
2368 @safe pure nothrow unittest
2370 auto a = [ 1, 2, 3 ];
2371 assert(!a.empty);
2372 assert(a[3 .. $].empty);
2374 int[string] b;
2375 assert(b.empty);
2376 b["zero"] = 0;
2377 assert(!b.empty);
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.
2387 @property inout(T)[] save(T)(return scope inout(T)[] a) @safe pure nothrow @nogc
2389 return a;
2393 @safe pure nothrow unittest
2395 auto a = [ 1, 2, 3 ];
2396 auto b = a.save;
2397 assert(b is a);
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).
2408 void popFront(T)(scope ref inout(T)[] a) @safe pure nothrow @nogc
2409 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2411 assert(a.length, "Attempting to popFront() past the end of an array of " ~ T.stringof);
2412 a = a[1 .. $];
2416 @safe pure nothrow unittest
2418 auto a = [ 1, 2, 3 ];
2419 a.popFront();
2420 assert(a == [ 2, 3 ]);
2423 @safe unittest
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); })));
2430 /// ditto
2431 void popFront(C)(scope ref inout(C)[] str) @trusted pure nothrow
2432 if (isAutodecodableString!(C[]))
2434 import std.algorithm.comparison : min;
2436 assert(str.length, "Attempting to popFront() past the end of an array of " ~ C.stringof);
2438 static if (is(immutable C == immutable char))
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
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];
2451 else static if (is(immutable C == immutable wchar))
2453 immutable u = str[0];
2454 immutable seqLen = 1 + (u >= 0xD800 && u <= 0xDBFF);
2455 str = str.ptr[min(seqLen, str.length) .. str.length];
2457 else static assert(0, "Bad template constraint.");
2460 @safe pure unittest
2462 import std.meta : AliasSeq;
2464 static foreach (S; AliasSeq!(string, wstring, dstring))
2466 S s = "\xC2\xA9hello";
2467 s.popFront();
2468 assert(s == "hello");
2470 S str = "hello\U00010143\u0100\U00010143";
2471 foreach (dchar c; ['h', 'e', 'l', 'l', 'o', '\U00010143', '\u0100', '\U00010143'])
2473 assert(str.front == c);
2474 str.popFront();
2476 assert(str.empty);
2478 static assert(!is(typeof({ immutable S a; popFront(a); })));
2479 static assert(!is(typeof({ typeof(S.init[0])[4] a; popFront(a); })));
2482 C[] _eatString(C)(C[] str)
2484 while (!str.empty)
2485 str.popFront();
2487 return str;
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);
2495 // https://issues.dlang.org/show_bug.cgi?id=16090
2496 @safe unittest
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);
2506 @safe unittest
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);
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).
2523 void popBack(T)(scope ref inout(T)[] a) @safe pure nothrow @nogc
2524 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2526 assert(a.length);
2527 a = a[0 .. $ - 1];
2531 @safe pure nothrow unittest
2533 auto a = [ 1, 2, 3 ];
2534 a.popBack();
2535 assert(a == [ 1, 2 ]);
2538 @safe unittest
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); })));
2545 /// ditto
2546 void popBack(T)(scope ref inout(T)[] a) @safe pure
2547 if (isAutodecodableString!(T[]))
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, $)];
2554 @safe pure unittest
2556 import std.meta : AliasSeq;
2558 static foreach (S; AliasSeq!(string, wstring, dstring))
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 == "");
2569 S str = "\U00010143\u0100\U00010143hello";
2570 foreach (dchar ch; ['o', 'l', 'l', 'e', 'h', '\U00010143', '\u0100', '\U00010143'])
2572 assert(str.back == ch);
2573 str.popBack();
2575 assert(str.empty);
2577 static assert(!is(typeof({ immutable S a; popBack(a); })));
2578 static assert(!is(typeof({ typeof(S.init[0])[4] a; popBack(a); })));
2583 EXPERIMENTAL: to try out removing autodecoding, set the version
2584 `NoAutodecodeStrings`. Most things are expected to fail with this version
2585 currently.
2587 version (NoAutodecodeStrings)
2589 enum autodecodeStrings = false;
2591 else
2594 enum autodecodeStrings = true;
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).
2605 @property ref inout(T) front(T)(return scope inout(T)[] a) @safe pure nothrow @nogc
2606 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2608 assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof);
2609 return a[0];
2613 @safe pure nothrow unittest
2615 int[] a = [ 1, 2, 3 ];
2616 assert(a.front == 1);
2619 @safe pure nothrow unittest
2621 auto a = [ 1, 2 ];
2622 a.front = 4;
2623 assert(a.front == 4);
2624 assert(a == [ 4, 2 ]);
2626 immutable b = [ 1, 2 ];
2627 assert(b.front == 1);
2629 int[2] c = [ 1, 2 ];
2630 assert(c.front == 1);
2633 /// ditto
2634 @property dchar front(T)(scope const(T)[] a) @safe pure
2635 if (isAutodecodableString!(T[]))
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);
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).
2651 @property ref inout(T) back(T)(return scope inout(T)[] a) @safe pure nothrow @nogc
2652 if (!isAutodecodableString!(T[]) && !is(T[] == void[]))
2654 assert(a.length, "Attempting to fetch the back of an empty array of " ~ T.stringof);
2655 return a[$ - 1];
2659 @safe pure nothrow unittest
2661 int[] a = [ 1, 2, 3 ];
2662 assert(a.back == 3);
2663 a.back += 4;
2664 assert(a.back == 7);
2667 @safe pure nothrow unittest
2669 immutable b = [ 1, 2, 3 ];
2670 assert(b.back == 3);
2672 int[3] c = [ 1, 2, 3 ];
2673 assert(c.back == 3);
2676 /// ditto
2677 // Specialization for strings
2678 @property dchar back(T)(scope const(T)[] a) @safe pure
2679 if (isAutodecodableString!(T[]))
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);
2688 Implements `length` for a range by forwarding it to `member`.
2690 package(std) mixin template ImplementLength(alias member)
2692 static if (hasLength!(typeof(member)))
2694 @property auto length()
2696 return member.length;
2698 alias opDollar = length;
2702 @safe unittest
2704 import std.meta : AliasSeq;
2706 foreach (alias E; AliasSeq!(noreturn, const(noreturn), immutable(noreturn) ))
2708 alias R = E[];
2710 static assert(isInputRange!R);
2711 static assert(isForwardRange!R);
2712 static assert(isBidirectionalRange!R);
2713 static assert(isRandomAccessRange!R);
2716 static assert(isOutputRange!(noreturn[], noreturn));