1 module evx.meta.traits;
2 
3 private {/**
4 	import}*/
5 	import std.range.primitives: front;
6 	import std.traits;
7 	import std.typetuple;
8 
9 	import evx.meta.match;
10 	import evx.meta.transform;
11 }
12 
13 /**
14 	
15 	domain of a function
16 */
17 alias Domain = ParameterTypeTuple;
18 
19 /**
20 	
21 	codomain of a function
22 */
23 alias Codomain = ReturnType;
24 
25 /**
26 	 test if identity is defined for a type 
27 */
28 enum has_identity (T...) = is (typeof(T[0].identity));
29 
30 // of symbols
31 /**
32 	 test if a symbol is a type 
33 */
34 enum is_type (T...) = is (T[0]);
35 
36 /**
37 	 test if a symbol is a class  
38 */
39 enum is_class (T...) = is(T[0] == class);
40 
41 /**
42 	 test if a symbol is a template  
43 */
44 enum is_template (T...) = __traits(isTemplate, T[0]);
45 
46 /**
47 	
48 	test if a type is const 
49 */
50 enum is_const (T...) = is (T[0] == const(T[0]));
51 
52 /**
53 	 test if a symbol refers to a function 
54 */
55 template is_function (T...)
56 {
57 	enum func () = isSomeFunction!(T[0]);
58 	enum temp () = isSomeFunction!(Instantiate!(T[0]));
59 
60 	enum is_function = Match!(func, temp);
61 }
62 
63 /**
64 	 test if a function is const 
65 */
66 template is_const_function (T...)
67 {
68 	enum yes () = staticIndexOf!(q{const}, __traits(getFunctionAttributes, T[0])) >= 0;
69 	enum no () = false;
70 
71 	enum is_const_function = Match!(yes, no);
72 }
73 
74 /**
75 	 test if a function is a lambda
76 */
77 enum is_lambda_function (alias f) = (is_function!f || is_template!f) && __traits(identifier, f)[0..`__lambda`.length] == `__lambda`;
78 
79 /**
80 	 test if a symbol has a numeric type 
81 */
82 template has_numeric_type (T...)
83 {
84 	static if (is (typeof(T[0]) == U, U))
85 		enum has_numeric_type = is_numeric!U;
86 	else enum has_numeric_type = false;
87 }
88 
89 /**
90 	 test if a symbol has a string type
91 */
92 template has_string_type (T...)
93 {
94 	static if (is (typeof(T[0]) == U, U))
95 		enum has_string_type = is_string!U;
96 	else enum has_string_type = false;
97 }
98 
99 /**
100 	 test if a variable has static storage class 
101 */
102 template is_static_variable (T...)
103 {
104 	static if (is (typeof(T[0]) == function))
105 		enum is_static_variable = false;
106 	else enum is_static_variable = is (typeof((){static f () {return &(T[0]);}}));
107 }
108 
109 // of types
110 /**
111 	 test if a type supports comparison operators <, <=, >, >= 
112 */
113 enum is_comparable (T...) = is (typeof(T[0].init < T[0].init) == bool);
114 
115 /**
116 	 test if a type is implicitly convertible to another 
117 */
118 alias is_implicitly_convertible = isImplicitlyConvertible;
119 
120 /**
121 	
122 	test if a type is a string 
123 */
124 alias is_string = isSomeString;
125 
126 /**
127 	
128 	test if a type is numeric 
129 */
130 alias is_numeric = isNumeric;
131 
132 /**
133 	 test if a type is a builtin floating point type 
134 */
135 alias is_floating_point = isFloatingPoint;
136 
137 /**
138 	 test if a type is a builtin integral type 
139 */
140 alias is_integral = isIntegral;
141 
142 /**
143 	 test if a type is unsigned 
144 */
145 alias is_unsigned = isUnsigned;
146 
147 /**
148 	 test if a type is signed 
149 */
150 alias is_signed = isSigned;
151 
152 /**
153 	 test if a type is a range 
154 */
155 enum is_range (R) = is (typeof(R.init.front.identity));
156 
157 /**
158 	 test if a range belongs to a given range category 
159 */
160 alias is_input_range = std.range.primitives.isInputRange;
161 /**
162     ditto
163 */
164 alias is_output_range = std.range.primitives.isOutputRange;
165 /**
166     ditto
167 */
168 alias is_forward_range = std.range.primitives.isForwardRange;
169 /**
170     ditto
171 */
172 alias is_bidirectional_range = std.range.primitives.isBidirectionalRange;
173 /**
174     ditto
175 */
176 alias is_random_access_range = std.range.primitives.isRandomAccessRange;
177 /**
178     ditto
179 */
180 alias has_length = std.range.primitives.hasLength;