1 module meta.udaIndex; 2 3 import std.traits : isFunction; 4 5 public template udaIndex(alias attr) 6 { 7 alias udaIndex = udaIndexImpl!(appropriateTest!attr); 8 } 9 10 private template udaIndexImpl(alias comparator) 11 { 12 template udaIndexImpl(attributes...) 13 { 14 mixin(generateUdaIndex!(attributes.length)); 15 } 16 } 17 18 private enum generateUdaIndex(int length) = generateUdaIndexImpl(0, length); 19 20 private string generateUdaIndexImpl(int base, int length) 21 { 22 import std.conv : to; 23 24 if (base == length) 25 { 26 if (length == 0) 27 { 28 return "enum udaIndexImpl = -1;"; 29 } 30 return " 31 { 32 enum udaIndexImpl = -1; 33 }"; 34 } 35 36 return "static if (comparator!(attributes[" ~ base.to!string ~ "])) 37 { 38 enum udaIndexImpl = " ~ base.to!string ~ "; 39 } 40 else " ~ generateUdaIndexImpl(base + 1, length); 41 } 42 43 // lhs that is a template 44 private template appropriateTest(alias lhs) 45 if (__traits(isTemplate, lhs)) 46 { 47 template appropriateTest(alias rhs) 48 { 49 static if (__traits(isSame, lhs, rhs)) 50 { 51 enum appropriateTest = true; 52 } 53 else static if (is(rhs: lhs!Args, Args...)) 54 { 55 enum appropriateTest = true; 56 } 57 else 58 { 59 enum appropriateTest = false; 60 } 61 } 62 } 63 64 // lhs that is a function 65 private template appropriateTest(alias lhs) 66 if (isFunction!lhs) 67 { 68 enum appropriateTest(alias rhs) = __traits(isSame, lhs, rhs); 69 } 70 71 // lhs that is a type 72 private template appropriateTest(alias lhs) 73 if (__traits(compiles, lhs.init)) 74 { 75 template appropriateTest(alias rhs) 76 { 77 static if (is(typeof(rhs) == lhs)) 78 { 79 enum appropriateTest = true; 80 } 81 else static if (is(rhs) && is(lhs == rhs)) 82 { 83 enum appropriateTest = true; 84 } 85 else 86 { 87 enum appropriateTest = false; 88 } 89 } 90 } 91 92 // lhs that is a value 93 private template appropriateTest(alias lhs) 94 if (__traits(compiles, typeof(lhs)) && !isFunction!lhs) 95 { 96 template appropriateTest(alias rhs) 97 { 98 static if (__traits(compiles, lhs == rhs)) 99 { 100 static if (lhs == rhs) 101 { 102 enum appropriateTest = true; 103 } 104 else 105 { 106 enum appropriateTest = false; 107 } 108 } 109 else 110 { 111 enum appropriateTest = false; 112 } 113 } 114 }