1 module libd.algorithm.common; 2 3 import libd.meta : isSlice, ElementType; 4 5 @nogc nothrow: 6 7 enum isInputRange(alias RangeT) = 8 ( 9 __traits(hasMember, RangeT, "front") 10 && __traits(hasMember, RangeT, "popFront") 11 && __traits(hasMember, RangeT, "empty") 12 ) 13 || isSlice!RangeT; 14 15 enum isOutputRange(alias RangeT, alias ElementT) = 16 __traits(compiles, RangeT.init.put(ElementT.init)); 17 18 enum isCollection(alias CollectionT, alias ElementT) = 19 __traits(hasMember, CollectionT, "insertAt") 20 && __traits(hasMember, CollectionT, "removeAt") 21 && __traits(hasMember, CollectionT, "getAt") 22 && __traits(hasMember, CollectionT, "length") 23 && is(typeof(CollectionT.init.getAt(0)) == ElementT) 24 && providesRange!CollectionT 25 && isOutputRange!(CollectionT, ElementT); 26 27 enum providesRange(alias T) = 28 __traits(hasMember, T, "range"); 29 30 enum canForeach(alias T) = 31 __traits(compiles, { foreach(a; T.init){} }); 32 33 enum canForeachOrProvidesRange(alias T) = 34 canForeach!T 35 || ( 36 providesRange!T 37 && canForeach!(typeof(T.range())) 38 ); 39 40 enum OptimisationHint 41 { 42 none = 0, 43 44 rangeFasterThanIndex = 1 << 0, 45 preferMoveOverCopy = 1 << 1 46 } 47 48 pragma(inline, true) 49 bool empty(T)(const scope auto ref T array) 50 if(isSlice!T) 51 { 52 return array.length == 0; 53 } 54 55 pragma(inline, true) 56 inout(ElementType!T) front(T)(scope auto ref inout(T) array) 57 if(isSlice!T) 58 { 59 assert(array.length, "Cannot use value of empty array."); 60 return array[0]; 61 } 62 63 pragma(inline, true) 64 void popFront(T)(scope auto ref T array) 65 if(isSlice!T) 66 { 67 array = array[1..$]; 68 }