1 module mutils.container.ct_map; 2 3 import std.meta; 4 import std.traits; 5 6 import mutils.meta; 7 8 struct CTMap(ElementsPar...) { 9 static assert(ElementsPar.length % 2 == 0); 10 alias Elements = ElementsPar; 11 12 struct KeyValue(alias KeyPar, alias ValPar) { 13 alias key = KeyPar; 14 alias value = ValPar; 15 } 16 17 struct KeyValue(alias KeyPar, ValPar) { 18 alias key = KeyPar; 19 alias value = ValPar; 20 } 21 22 struct KeyValue(KeyPar, alias ValPar) { 23 alias key = KeyPar; 24 alias value = ValPar; 25 } 26 27 template getValues() { 28 alias getValues = removeEven!Elements; 29 } 30 31 template getKeys() { 32 alias getKeys = removeOdd!Elements; 33 } 34 35 template getValueType() { 36 static assert(valuesHaveSameType); 37 alias getValueType = typeof(Elements[1]); 38 } 39 40 template getKeyType() { 41 static assert(keysHaveSameType); 42 alias getKeyType = typeof(Elements[0]); 43 } 44 45 static bool valuesAreValueType() { 46 return allSatisfy!(isExpressions, getValues!()); 47 } 48 49 static bool keysAreValueType() { 50 return allSatisfy!(isExpressions, getKeys!()); 51 } 52 53 static bool valuesHaveSameType() { 54 static if (keysAreValueType) { 55 alias Types = staticMap!(getType, getValues!()); 56 return NoDuplicates!(Types).length == 1; 57 } else { 58 return false; 59 } 60 } 61 62 static bool keysHaveSameType() { 63 static if (keysAreValueType) { 64 alias Types = staticMap!(getType, getKeys!()); 65 return NoDuplicates!(Types).length == 1; 66 } else { 67 return false; 68 } 69 } 70 71 template getImpl() { 72 auto getImpl() { 73 foreach (i, Key; Elements) { 74 static if (i % 2 == 0 && ((__traits(compiles, T == Key) 75 && T == Key) || (__traits(compiles, is(T == Key)) && is(T == Key)))) { //even elements are keys 76 struct Returner { 77 static if (isExpressions!(Elements[i + 1])) { 78 enum value = Elements[i + 1]; 79 } else { 80 alias value = Elements[i + 1]; 81 } 82 } 83 84 Returner ret; 85 return ret; 86 } 87 88 } 89 } 90 91 } 92 93 static auto get(T)() { 94 mixin getImpl; 95 return getImpl(); 96 } 97 98 static auto get(alias T)() { 99 mixin getImpl; 100 return getImpl(); 101 } 102 103 //static if(valuesHaveSameType && keysHaveSameType){ 104 alias byKeyValue = toKeyValue!(Elements); 105 //} 106 107 private template toKeyValue(Arr...) { 108 static if (Arr.length > 2) { 109 alias toKeyValue = AliasSeq!(KeyValue!(Arr[0], Arr[1]), toKeyValue!(Arr[2 .. $])); 110 } else static if (Arr.length == 2) { 111 alias toKeyValue = AliasSeq!(KeyValue!(Arr[0], Arr[1])); 112 } else { 113 alias toKeyValue = AliasSeq!(); 114 } 115 } 116 117 } 118 119 unittest { 120 alias myMap = CTMap!(6, int, long, 12, 18, 23); 121 122 static assert(is(myMap.get!(6).value == int)); 123 static assert(myMap.get!(long).value == 12); 124 static assert(myMap.get!(18).value == 23); 125 static assert(!myMap.keysAreValueType); 126 static assert(!myMap.valuesAreValueType); 127 } 128 129 unittest { 130 alias myMap = CTMap!("str1", 8, "str2", 12, "str3", 23); 131 132 static assert(myMap.keysAreValueType); 133 static assert(myMap.valuesAreValueType); 134 static assert(myMap.keysHaveSameType); 135 static assert(myMap.valuesHaveSameType); 136 static assert(is(myMap.getValueType!() == int)); 137 static assert(is(myMap.getKeyType!() == string)); 138 139 } 140 141 unittest { 142 alias myMap = CTMap!("str1", 8, "str2", 12, "str3", 23); 143 144 int runtimeLookUp(string var) { 145 switch (var) { 146 foreach (keyValue; myMap.byKeyValue) { 147 case keyValue.key: 148 return keyValue.value; 149 } 150 default: 151 return 0; 152 } 153 } 154 155 assert(runtimeLookUp("str0") == 0); 156 assert(runtimeLookUp("str1") == 8); 157 assert(runtimeLookUp("str2") == 12); 158 assert(runtimeLookUp("str3") == 23); 159 assert(runtimeLookUp("str4") == 0); 160 }