1 /** 2 Templates to facilitate treating $(LINK2 ./package.html#SmartInt, `checkedint.SmartInt`) and $(LINK2 ./package.html#SafeInt, `checkedint.SafeInt`) like the built-in numeric types in 3 generic code. 4 5 Copyright: Copyright Thomas Stuart Bockman 2015 6 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 7 Authors: Thomas Stuart Bockman 8 9 This module wraps various templates from `std.traits` to make them `checkedint`-aware. For example, 10 `std.traits.isSigned!(SmartInt!int)` is `false`, but `checkedint.traits.isSigned!(SmartInt!int)` is `true`. 11 12 This module is separate from `checkedint` because it is only useful in generic code, and its symbols (deliberately) 13 conflict with some from `std.traits`. 14 **/ 15 module checkedint.traits; 16 import checkedint.asserts : SmartInt; 17 18 import std.meta : AliasSeq; 19 20 // checkedint.flags ////////////////////////////////////// 21 static import checkedint.flags; 22 23 /// See $(LINK2 ./flags.html#intFlagPolicyOf, `checkedint.flags.intFlagPolicyOf`) 24 alias intFlagPolicyOf = checkedint.flags.intFlagPolicyOf; 25 26 27 // checkedint //////////////////////////////////////////// 28 static import chkd = checkedint; 29 30 /// See $(LINK2 ./package.html#isSafeInt, `checkedint.isSafeInt`) 31 alias isSafeInt = chkd.isSafeInt; 32 33 /// See $(LINK2 ./package.html#isSmartInt, `checkedint.isSmartInt`) 34 alias isSmartInt = chkd.isSmartInt; 35 36 /// See $(LINK2 ./package.html#isCheckedInt, `checkedint.isCheckedInt`) 37 alias isCheckedInt = chkd.isCheckedInt; 38 39 /// See $(LINK2 ./package.html#hasBitOps, `checkedint.hasBitOps`) 40 alias hasBitOps = chkd.hasBitOps; 41 42 /// See $(LINK2 ./package.html#BasicScalar, `checkedint.BasicScalar`) 43 alias BasicScalar = chkd.BasicScalar; 44 45 46 // std.traits //////////////////////////////////////////// 47 static import bsct = future.traits0; 48 49 private template isEx(alias Predicate, T) 50 { 51 static if (isCheckedInt!T) 52 enum isEx = Predicate!(BasicScalar!T); 53 else 54 enum isEx = Predicate!T; 55 } 56 57 /// See `std.traits.isScalarType` 58 alias isBasicScalar = bsct.isScalarType; 59 /// `checkedint`-aware wrapper for `std.traits.isScalarType` 60 template isScalarType(T) 61 { 62 alias isScalarType = isEx!(isBasicScalar, T); 63 } 64 /// 65 unittest 66 { 67 foreach (T; AliasSeq!(int, ushort, double, bool)) 68 assert(isBasicScalar!T && isScalarType!T); 69 70 assert(!isBasicScalar!(SmartInt!int)); 71 assert( isScalarType!(SmartInt!int)); 72 73 foreach (T; AliasSeq!(int[])) 74 assert(!(isBasicScalar!T || isScalarType!T)); 75 } 76 77 /// See `std.traits.isNumeric` 78 alias isBasicNum = bsct.isNumeric; 79 /// `checkedint`-aware wrapper for `std.traits.isNumeric` 80 template isNumeric(T) 81 { 82 alias isNumeric = isEx!(isBasicNum, T); 83 } 84 /// 85 unittest 86 { 87 foreach (T; AliasSeq!(int, ushort, double)) 88 assert(isBasicNum!T && isNumeric!T); 89 90 assert(!isBasicNum!(SmartInt!int)); 91 assert( isNumeric!(SmartInt!int)); 92 93 foreach (T; AliasSeq!(int[], bool)) 94 assert(!(isBasicNum!T || isNumeric!T)); 95 } 96 97 /// See `std.traits.isFloatingPoint` 98 alias isFloatingPoint = bsct.isFloatingPoint; 99 100 /// See `future.traits.isFixedPoint` 101 alias isBasicFixed = bsct.isFixedPoint; 102 /// `checkedint`-aware wrapper for `future.traits.isFixedPoint` 103 template isFixedPoint(T) 104 { 105 alias isFixedPoint = isEx!(isBasicFixed, T); 106 } 107 /// 108 unittest 109 { 110 foreach (T; AliasSeq!(int, ushort, bool)) 111 assert(isBasicFixed!T && isFixedPoint!T); 112 113 assert(!isBasicFixed!(SmartInt!int)); 114 assert( isFixedPoint!(SmartInt!int)); 115 116 foreach (T; AliasSeq!(double, int[])) 117 assert(!(isBasicFixed!T || isFixedPoint!T)); 118 } 119 120 /// See `std.traits.isIntegral` 121 alias isBasicInt = bsct.isIntegral; 122 /// `checkedint`-aware wrapper for `std.traits.isIntegral` 123 template isIntegral(T) 124 { 125 alias isIntegral = isEx!(isBasicInt, T); 126 } 127 /// 128 unittest 129 { 130 foreach (T; AliasSeq!(int, ushort)) 131 assert(isBasicInt!T && isIntegral!T); 132 133 assert(!isBasicInt!(SmartInt!int)); 134 assert( isIntegral!(SmartInt!int)); 135 136 foreach (T; AliasSeq!(double, int[], bool)) 137 assert(!(isBasicInt!T || isIntegral!T)); 138 } 139 140 /// See `std.traits.isSomeChar` 141 alias isSomeChar = bsct.isSomeChar; 142 /// See `std.traits.isBoolean` 143 alias isBoolean = bsct.isBoolean; 144 145 /// See `std.traits.isSigned` 146 alias isBasicSigned = bsct.isSigned; 147 /// `checkedint`-aware wrapper for `std.traits.isSigned` 148 template isSigned(T) 149 { 150 alias isSigned = isEx!(isBasicSigned, T); 151 } 152 /// 153 unittest 154 { 155 foreach (T; AliasSeq!(int, double)) 156 assert(isBasicSigned!T && isSigned!T); 157 158 assert(!isBasicSigned!(SmartInt!int)); 159 assert( isSigned!(SmartInt!int)); 160 161 foreach (T; AliasSeq!(ushort, int[], bool)) 162 assert(!(isBasicSigned!T || isSigned!T)); 163 } 164 165 /// See `std.traits.isUnsigned` 166 alias isBasicUnsigned = bsct.isUnsigned; 167 /// `checkedint`-aware wrapper for `isUnsigned` 168 template isUnsigned(T) 169 { 170 alias isUnsigned = isEx!(isBasicUnsigned, T); 171 } 172 /// 173 unittest 174 { 175 foreach (T; AliasSeq!(ushort)) 176 assert(isBasicUnsigned!T && isUnsigned!T); 177 178 assert(!isBasicUnsigned!(SmartInt!uint)); 179 assert( isUnsigned!(SmartInt!uint)); 180 181 foreach (T; AliasSeq!(double, int[], bool)) 182 assert(!(isBasicUnsigned!T || isUnsigned!T)); 183 } 184 185 /// `checkedint`-aware version of `std.traits.mostNegative` 186 template mostNegative(T) 187 if (isNumeric!T) 188 { 189 static if (isFloatingPoint!T) 190 enum mostNegative = -T.max; 191 else 192 enum mostNegative = T.min; 193 } 194 /// 195 unittest 196 { 197 assert(mostNegative!int == int.min); 198 static assert(is(typeof(mostNegative!int) == int)); 199 assert(mostNegative!(SmartInt!int) == SmartInt!(int).min); 200 static assert(is(typeof(mostNegative!(SmartInt!int)) == SmartInt!int)); 201 } 202 203 private template TransEx(alias TypeTransform, T) 204 { 205 static if (isCheckedInt!T) 206 { 207 import checkedint : SmartInt, SafeInt; 208 import future.traits0 : CopyTypeQualifiers, Select; 209 210 alias TTB = TypeTransform!(CopyTypeQualifiers!(T, BasicScalar!T)); 211 alias CheckedInt = Select!(isSmartInt!T, SmartInt, SafeInt); 212 alias TransEx = CopyTypeQualifiers!(TTB, CheckedInt!(TTB, intFlagPolicyOf!T, hasBitOps!T)); 213 } else 214 alias TransEx = TypeTransform!T; 215 } 216 217 /// `checkedint`-aware wrapper for `std.traits.Signed` 218 template Signed(T) 219 { 220 alias Signed = TransEx!(bsct.Signed, T); 221 } 222 /// 223 unittest 224 { 225 static assert(is(Signed!int == int)); 226 static assert(is(Signed!(SmartInt!int) == SmartInt!int)); 227 static assert(is(Signed!ulong == long)); 228 static assert(is(Signed!(SmartInt!ulong) == SmartInt!long)); 229 } 230 231 /// `checkedint`-aware wrapper for `std.traits.Unsigned` 232 template Unsigned(T) 233 { 234 alias Unsigned = TransEx!(bsct.Unsigned, T); 235 } 236 /// 237 unittest 238 { 239 static assert(is(Unsigned!int == uint)); 240 static assert(is(Unsigned!(SmartInt!int) == SmartInt!uint)); 241 static assert(is(Unsigned!ulong == ulong)); 242 static assert(is(Unsigned!(SmartInt!ulong) == SmartInt!ulong)); 243 } 244 245 /// `checkedint`-aware wrapper for `future.traits.Promoted` 246 template Promoted(T) 247 { 248 alias Promoted = TransEx!(bsct.Promoted, T); 249 } 250 /// 251 unittest 252 { 253 static assert(is(Promoted!byte == int)); 254 static assert(is(Promoted!(SmartInt!byte) == SmartInt!int)); 255 static assert(is(Promoted!int == int)); 256 static assert(is(Promoted!(SmartInt!int) == SmartInt!int)); 257 }