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 satisfy checks - extension of std.typecons (allSatisfy);
7 */
8 module stribog.meta.satisfy;
9 
10 public import std.typetuple : allSatisfy, anySatisfy;
11 
12 import std.conv : text;
13 
14 import stribog.meta.base;
15 
16 /**
17 *   Same as std.typetuple.allSatisfy, but passes $(B i) arguments to the first template.
18 */
19 template allSatisfyN(size_t i, alias F, T...)
20 {
21     static assert(T.length % i == 0, text("Invalid count of arguments, expected ", i, " but got ", T.length));
22     
23     static if (T.length < i)
24     {
25         enum allSatisfyN = true;
26     }
27     else static if (T.length == i)
28     {
29         static if(__traits(compiles, F(T[0 .. i]))) {
30         	enum allSatisfyN = F(T[0 .. i]);
31         }
32         else {
33         	enum allSatisfyN = F!(T[0 .. i]);
34     	}
35     }
36     else
37     {
38         static if(!F!(T[0 .. i]))
39         	enum allSatisfyN = false;
40     	else
41     		enum allSatisfyN = allSatisfyN!(i, F, T[i  .. $]);
42     }
43 }
44 /// Example
45 unittest
46 {
47     template Test(T...)
48     {
49         enum Test = is(typeof(T[0]) == string) && is(typeof(T[1]) == bool);
50     }
51 
52     static assert(allSatisfyN!(2, Test, "42", true, "108", false));
53 }
54 
55 /// alias to allSatisfyN for 2 arguments
56 alias allSatisfy2(alias F, T...) = allSatisfyN!(2, F, T);
57 /// alias to allSatisfyN for 3 arguments
58 alias allSatisfy3(alias F, T...) = allSatisfyN!(3, F, T);
59 /// alias to allSatisfyN for 4 arguments
60 alias allSatisfy4(alias F, T...) = allSatisfyN!(4, F, T);
61 /// alias to allSatisfyN for 5 arguments
62 alias allSatisfy5(alias F, T...) = allSatisfyN!(5, F, T);
63 /// alias to allSatisfyN for 6 arguments
64 alias allSatisfy6(alias F, T...) = allSatisfyN!(6, F, T);
65 /// alias to allSatisfyN for 7 arguments
66 alias allSatisfy7(alias F, T...) = allSatisfyN!(7, F, T);
67 /// alias to allSatisfyN for 8 arguments
68 alias allSatisfy8(alias F, T...) = allSatisfyN!(8, F, T);
69 /// alias to allSatisfyN for 9 arguments
70 alias allSatisfy9(alias F, T...) = allSatisfyN!(9, F, T);
71 
72 /**
73 *   Same as std.typetuple anySatisfy, but passes $(B i) arguments to $(B F).
74 */
75 template anySatisfyN(size_t i, alias F, T...)
76 {
77     static assert(T.length % i == 0, text("Invalid count of arguments, expected ", i, " but got ", T.length));
78     
79     static if (T.length < i)
80     {
81         enum anySatisfyN = true;
82     }
83     else static if (T.length == i)
84     {
85         static if(__traits(compiles, F(T[0 .. i]))) {
86             enum anySatisfyN = F(T[0 .. i]);
87         }
88         else {
89             enum anySatisfyN = F!(T[0 .. i]);
90         }
91     }
92     else
93     {
94         static if(F!(T[0 .. i]))
95         	enum anySatisfyN = true;
96     	else
97     		enum anySatisfyN = anySatisfyN!(i, F, T[i  .. $]);
98     }
99 }
100 /// Example
101 unittest
102 {
103     template Test(int a, int b, int c) {
104         enum Test = a + b == c;
105     }
106     
107     static assert(!anySatisfyN!(3, Test, 1, 1, 3, 5, 8, 11)); 
108     static assert( anySatisfyN!(3, Test, 1, 1, 2, 5, 8, 11)); 
109 }
110 
111 /// alias of anySatisfyN for 2 arguments
112 alias anySatisfy2(alias F, T...) = anySatisfyN!(2, F, T);
113 /// alias of anySatisfyN for 3 arguments
114 alias anySatisfy3(alias F, T...) = anySatisfyN!(3, F, T);
115 /// alias of anySatisfyN for 4 arguments
116 alias anySatisfy4(alias F, T...) = anySatisfyN!(4, F, T);
117 /// alias of anySatisfyN for 5 arguments
118 alias anySatisfy5(alias F, T...) = anySatisfyN!(5, F, T);
119 /// alias of anySatisfyN for 6 arguments
120 alias anySatisfy6(alias F, T...) = anySatisfyN!(6, F, T);
121 /// alias of anySatisfyN for 7 arguments
122 alias anySatisfy7(alias F, T...) = anySatisfyN!(7, F, T);
123 /// alias of anySatisfyN for 8 arguments
124 alias anySatisfy8(alias F, T...) = anySatisfyN!(8, F, T);
125 /// alias of anySatisfyN for 9 arguments
126 alias anySatisfy9(alias F, T...) = anySatisfyN!(9, F, T);