1 /** 2 * Copyright: © 2014-2015 Anton Gushcha 3 * License: Subject to the terms of the Boost 1.0 license as specified in LICENSE file 4 * Authors: Anton Gushcha <ncrashed@gmail.com> 5 * 6 * Template filters - extension of std.typecons; 7 */ 8 module stribog.meta.filter; 9 10 import std.conv : text; 11 12 import stribog.meta.base; 13 14 /** 15 * Performs filtering of expression tuple $(B T) one by one by function or template $(B F). If $(B F) 16 * returns $(B true) the resulted element goes to returned expression tuple, else it is discarded. 17 */ 18 template staticFilter(alias F, T...) 19 { 20 static if(T.length == 0) 21 { 22 alias staticFilter = ExpressionList!(); 23 } 24 else 25 { 26 static if(__traits(compiles, F(T[0])) && F(T[0]) 27 || __traits(compiles, F!(T[0])) && F!(T[0])) 28 { 29 alias staticFilter = ExpressionList!(T[0], staticFilter!(F, T[1 .. $])); 30 } 31 else 32 { 33 alias staticFilter = ExpressionList!(staticFilter!(F, T[1 .. $])); 34 } 35 } 36 } 37 /// Example 38 unittest 39 { 40 import std.conv; 41 42 bool testFunc(int val) 43 { 44 return val <= 15; 45 } 46 47 template testTemplate(int val) 48 { 49 enum testTemplate = val <= 15; 50 } 51 52 static assert(staticFilter!(testFunc, ExpressionList!(42, 108, 15, 2)) == ExpressionList!(15, 2)); 53 static assert(staticFilter!(testTemplate, ExpressionList!(42, 108, 15, 2)) == ExpressionList!(15, 2)); 54 } 55 56 /** 57 * Performs filtering of expression tuple $(B T) passing $(B i) elements to function or template $(B F). If $(B F) 58 * returns $(B true) the resulted elements go to returned expression tuple, else it is discarded. 59 */ 60 template staticFilterN(size_t i, alias F, T...) 61 { 62 static assert(i != 0, "staticFilterN: N is zero"); 63 static assert(T.length % i == 0, text("Wrong size of ExpressionList in filter, expected ", i, " but got ", T.length)); 64 65 static if(T.length < i) 66 { 67 alias staticFilterN = ExpressionList!(); 68 } 69 else 70 { 71 static if(__traits(compiles, F(T[0 .. i])) && F(T[0 .. i]) 72 || __traits(compiles, F!(T[0 .. i])) && F!(T[0 .. i])) 73 { 74 alias staticFilterN = ExpressionList!(T[0 .. i], staticFilterN!(i, F, T[i .. $])); 75 } 76 else 77 { 78 alias staticFilterN = ExpressionList!(staticFilterN!(i, F, T[i .. $])); 79 } 80 } 81 } 82 /// Example 83 unittest 84 { 85 template isNineSumm(int a, int b, int c) { enum isNineSumm = a + b + c == 9; } 86 static assert( staticEqual!( StrictExpressionList!(staticFilterN!(3, isNineSumm, 3, 3, 3, 1, 1, 1, 2, 4, 3)), StrictExpressionList!(ExpressionList!(3, 3, 3, 2, 4, 3)) ) ); 87 } 88 89 /// Alias of staticFilterN for 2 arguments 90 alias staticFilter2(alias F, T...) = staticFilterN!(2, F, T); 91 /// Alias of staticFilterN for 3 arguments 92 alias staticFilter3(alias F, T...) = staticFilterN!(3, F, T); 93 /// Alias of staticFilterN for 4 arguments 94 alias staticFilter4(alias F, T...) = staticFilterN!(4, F, T); 95 /// Alias of staticFilterN for 5 arguments 96 alias staticFilter5(alias F, T...) = staticFilterN!(5, F, T); 97 /// Alias of staticFilterN for 6 arguments 98 alias staticFilter6(alias F, T...) = staticFilterN!(6, F, T); 99 /// Alias of staticFilterN for 7 arguments 100 alias staticFilter7(alias F, T...) = staticFilterN!(7, F, T); 101 /// Alias of staticFilterN for 8 arguments 102 alias staticFilter8(alias F, T...) = staticFilterN!(8, F, T); 103 /// Alias of staticFilterN for 9 arguments 104 alias staticFilter9(alias F, T...) = staticFilterN!(9, F, T); 105 106 /** 107 * Performs filtering of expression tuple $(B T) passing $(B i) elements to function or template $(B F). If $(B F) 108 * returns $(B true) the first element go to returned expression tuple and "window" is moved over T by 1 element. 109 * Last i-1 elements goes to resulted tuple without checks. 110 */ 111 template staticFilterLookaheadN(size_t i, alias F, T...) 112 { 113 static assert(i != 0, "staticFilterLookaheadN: N is zero"); 114 115 static if(T.length < i) 116 { 117 alias staticFilterLookaheadN = ExpressionList!(T); 118 } 119 else 120 { 121 static if(__traits(compiles, F(T[0 .. i])) && F(T[0 .. i]) 122 || __traits(compiles, F!(T[0 .. i])) && F!(T[0 .. i])) 123 { 124 alias staticFilterLookaheadN = ExpressionList!(T[0], staticFilterLookaheadN!(i, F, T[1 .. $])); 125 } 126 else 127 { 128 alias staticFilterLookaheadN = ExpressionList!(staticFilterLookaheadN!(i, F, T[1 .. $])); 129 } 130 } 131 } 132 /// Example 133 unittest 134 { 135 template isFibonachi(int a, int b, int c) { enum isFibonachi = a == b + c; } 136 static assert( staticEqual!( StrictExpressionList!(staticFilterLookaheadN!(3, isFibonachi, 9, 5, 3, 2, 1, 1)), StrictExpressionList!(ExpressionList!(5, 3, 2, 1, 1)) ) ); 137 } 138 139 /// Alias of staticFilterLookaheadN for 1 argument 140 alias staticFilterLookahead(alias F, T...) = staticFilterLookaheadN!(1, F, T); 141 /// Alias of staticFilterLookaheadN for 2 arguments 142 alias staticFilterLookahead2(alias F, T...) = staticFilterLookaheadN!(2, F, T); 143 /// Alias of staticFilterLookaheadN for 3 arguments 144 alias staticFilterLookahead3(alias F, T...) = staticFilterLookaheadN!(3, F, T); 145 /// Alias of staticFilterLookaheadN for 4 arguments 146 alias staticFilterLookahead4(alias F, T...) = staticFilterLookaheadN!(4, F, T); 147 /// Alias of staticFilterLookaheadN for 5 arguments 148 alias staticFilterLookahead5(alias F, T...) = staticFilterLookaheadN!(5, F, T); 149 /// Alias of staticFilterLookaheadN for 6 arguments 150 alias staticFilterLookahead6(alias F, T...) = staticFilterLookaheadN!(6, F, T); 151 /// Alias of staticFilterLookaheadN for 7 arguments 152 alias staticFilterLookahead7(alias F, T...) = staticFilterLookaheadN!(7, F, T); 153 /// Alias of staticFilterLookaheadN for 8 arguments 154 alias staticFilterLookahead8(alias F, T...) = staticFilterLookaheadN!(8, F, T); 155 /// Alias of staticFilterLookaheadN for 9 arguments 156 alias staticFilterLookahead9(alias F, T...) = staticFilterLookaheadN!(9, F, T); 157 158 /** 159 * Performs filtering of expression tuple $(B T) passing $(B i) elements to function or template $(B F). If $(B F) 160 * returns $(B true) the last element go to returned expression tuple and "window" is moved behind T by 1 element. 161 * First i-1 elements goes to resulted tuple without checks. 162 * 163 * Filtering starts from last element. 164 */ 165 template staticFilterLookbehindN(size_t i, alias F, T...) 166 { 167 static assert(i != 0, "staticFilterLookbehindN: N is zero"); 168 169 static if(T.length < i) 170 { 171 alias staticFilterLookbehindN = ExpressionList!(T); 172 } 173 else 174 { 175 static if(__traits(compiles, F(T[$-i .. $])) && F(T[$-i .. $]) 176 || __traits(compiles, F!(T[$-i .. $])) && F!(T[$-i .. $])) 177 { 178 alias staticFilterLookbehindN = ExpressionList!(staticFilterLookbehindN!(i, F, T[0 .. $-1]), T[$-1]); 179 } 180 else 181 { 182 alias staticFilterLookbehindN = ExpressionList!(staticFilterLookbehindN!(i, F, T[0 .. $-1])); 183 } 184 } 185 } 186 /// Example 187 unittest 188 { 189 template isFibonachi(int a, int b, int c) { enum isFibonachi = a + b == c; } 190 static assert( staticEqual!( StrictExpressionList!(staticFilterLookbehindN!(3, isFibonachi, 1, 1, 2, 3, 5, 9)), StrictExpressionList!(ExpressionList!(1, 1, 2, 3, 5)) ) ); 191 } 192 193 /// Alias of staticFilterLookbehindN for 1 argument 194 alias staticFilterLookbehind(alias F, T...) = staticFilterLookbehindN!(1, F, T); 195 /// Alias of staticFilterLookbehindN for 2 arguments 196 alias staticFilterLookbehind2(alias F, T...) = staticFilterLookbehindN!(2, F, T); 197 /// Alias of staticFilterLookbehindN for 3 arguments 198 alias staticFilterLookbehind3(alias F, T...) = staticFilterLookbehindN!(3, F, T); 199 /// Alias of staticFilterLookbehindN for 4 arguments 200 alias staticFilterLookbehind4(alias F, T...) = staticFilterLookbehindN!(4, F, T); 201 /// Alias of staticFilterLookbehindN for 5 arguments 202 alias staticFilterLookbehind5(alias F, T...) = staticFilterLookbehindN!(5, F, T); 203 /// Alias of staticFilterLookbehindN for 6 arguments 204 alias staticFilterLookbehind6(alias F, T...) = staticFilterLookbehindN!(6, F, T); 205 /// Alias of staticFilterLookbehindN for 7 arguments 206 alias staticFilterLookbehind7(alias F, T...) = staticFilterLookbehindN!(7, F, T); 207 /// Alias of staticFilterLookbehindN for 8 arguments 208 alias staticFilterLookbehind8(alias F, T...) = staticFilterLookbehindN!(8, F, T); 209 /// Alias of staticFilterLookbehindN for 9 arguments 210 alias staticFilterLookbehind9(alias F, T...) = staticFilterLookbehindN!(9, F, T);