1 /// Library for iterating over stuff 2 module mecca.lib.iteration; 3 4 // Licensed under the Boost license. Full copyright information in the AUTHORS file 5 6 import std.traits; 7 import std.range; 8 9 import mecca.lib.reflection; 10 11 /** 12 Turn a Ref returning input range into a PTR one. 13 14 This is useful for using ranges iterating `@disable this(this)` types with Phobos, that requires `front` to be 15 copyable in order to recognize a range as an input range. 16 */ 17 auto ptrInputRange(Range)(Range range) if( isRefInputRange!Range ) { 18 struct PtrRange { 19 Range range; 20 21 @property auto front() { 22 return &(range.front()); 23 } 24 25 alias range this; 26 } 27 28 return PtrRange(range); 29 } 30 31 /// ditto 32 auto ptrInputRange(T)(T[] slice) { 33 struct PtrRange { 34 T[] slice; 35 36 @property bool empty() pure const @safe @nogc { 37 return slice.length == 0; 38 } 39 40 void popFront() @safe @nogc { 41 slice = slice[1..$]; 42 } 43 44 @property T* front() pure @safe @nogc { 45 return &slice[0]; 46 } 47 } 48 49 return PtrRange(slice); 50 } 51 52 unittest { 53 import std.algorithm : map, equal; 54 55 struct Uncopyable { 56 uint a; 57 58 @disable this(this); 59 } 60 61 Uncopyable[5] arr; 62 foreach(i; 0..5) { 63 arr[i] = Uncopyable(i); 64 } 65 66 assert( equal( arr.ptrInputRange.map!"(*a).a*2", [0, 2, 4, 6, 8] ) ); 67 } 68 69 auto derefRange(Range)(Range range) if( isInputRange!Range && is( isPointer!(elementType!Range) ) ) { 70 struct DerefRange { 71 Range range; 72 73 @property ref auto front() { 74 return *range.front; 75 } 76 77 alias range this; 78 } 79 80 return DerefRange(range); 81 }