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;