1 /** 2 Static introspection utilties for ranges 3 */ 4 module bolts.range; 5 6 import bolts.internal; 7 import std.range : isInputRange; 8 import std.meta : allSatisfy; 9 10 /** 11 True if R is a `SortedRange` 12 13 See_Also: 14 `std.range.SortedRange` 15 */ 16 template isSortedRange(R...) if (R.length == 1) { 17 import std.range: SortedRange; 18 import bolts.traits: TypesOf; 19 alias T = TypesOf!R[0]; 20 enum isSortedRange = is(T : SortedRange!U, U...); 21 } 22 23 /// 24 unittest { 25 import std.algorithm: sort; 26 import std.range: assumeSorted; 27 static assert(isSortedRange!(typeof([0, 1, 2])) == false); 28 static assert(isSortedRange!([0, 1, 2].sort) == true); 29 static assert(isSortedRange!(typeof([0, 1, 2].assumeSorted)) == true); 30 static assert(isSortedRange!int == false); 31 } 32 33 /** 34 Given a `SortedRange` R, `sortingPredicate!R(a, b)` will call in to the predicate 35 that was used to create the `SortedRange` 36 37 Params: 38 Args[0] = the range to extract the predicate from 39 Args[1] = the sorting predicate to fallback to if `Range` is not a `SortedRange` 40 */ 41 template sortingPredicate(Args...) 42 if ((Args.length == 1 || Args.length == 2) && isInputRange!(from.bolts.traits.TypesOf!Args[0])) { 43 import bolts.traits: TypesOf; 44 import std.range: SortedRange; 45 import std.functional: binaryFun; 46 alias R = TypesOf!Args[0]; 47 static if (is(R : SortedRange!P, P...)) { 48 alias sortingPredicate = binaryFun!(P[1]); 49 } else { 50 static if (Args.length == 2) { 51 alias pred = binaryFun!(Args[1]); 52 } else { 53 alias pred = (a, b) => a < b; 54 } 55 alias sortingPredicate = pred; 56 } 57 } 58 59 /// 60 unittest { 61 import std.algorithm: sort; 62 63 // As a type 64 assert(sortingPredicate!(typeof([1].sort!"a < b"))(1, 2) == true); 65 assert(sortingPredicate!(typeof([1].sort!((a, b) => a > b)))(1, 2) == false); 66 67 // As a value 68 assert(sortingPredicate!([1].sort!"a > b")(1, 2) == false); 69 assert(sortingPredicate!([1].sort!((a, b) => a < b))(1, 2) == true); 70 71 // Default predicate 72 assert(sortingPredicate!(int[])(1, 2) == true); 73 } 74 75 /// Finds the CommonType of a list of ranges 76 template CommonTypeOfRanges(Rs...) if (allSatisfy!(isInputRange, Rs)) { 77 import std.traits: CommonType; 78 import std.meta: staticMap; 79 import std.range: ElementType; 80 alias CommonTypeOfRanges = CommonType!(staticMap!(ElementType, Rs)); 81 } 82 83 /// 84 unittest { 85 auto a = [1, 2]; 86 auto b = [1.0, 2.0]; 87 static assert(is(CommonTypeOfRanges!(typeof(a), typeof(b)) == double)); 88 }