1 module unecht.meta.uda; 2 3 alias aliasHelper(alias T) = T; 4 alias aliasHelper(T) = T; 5 6 /// 7 private template getUDAIndex(alias UDA, ATTR...) 8 { 9 template findUDA(int i) 10 { 11 static if(ATTR.length == 0) 12 { 13 enum findUDA = -1; 14 } 15 else static if(i >= ATTR.length) 16 { 17 enum findUDA = -1; 18 } 19 else 20 { 21 static if(is(aliasHelper!(ATTR[i]) == UDA) || is(typeof(ATTR[i]) == UDA)) 22 { 23 enum findUDA = i; 24 } 25 else 26 { 27 enum findUDA = findUDA!(i+1); 28 } 29 } 30 } 31 32 enum getUDAIndex = findUDA!(0); 33 } 34 35 /// 36 template hasUDA(alias T, alias UDA) 37 { 38 enum hasUDA = getUDAIndex!(UDA,__traits(getAttributes, T)) != -1; 39 } 40 41 /// 42 template getUDA(alias T, alias UDA) 43 { 44 template findUDA(ATTR...) 45 { 46 static if(hasUDA!(T, UDA)) 47 { 48 enum findUDA = ATTR[getUDAIndex!(UDA, ATTR)]; 49 } 50 else 51 { 52 import std..string:format; 53 static assert(0, format("UDA '%s' not found for Type '%s'", UDA.stringof, T.stringof)); 54 } 55 } 56 enum getUDA = findUDA!(__traits(getAttributes, T)); 57 } 58 59 unittest 60 { 61 struct e{} 62 63 struct A{ 64 @A 65 string bar; 66 } 67 68 @e 69 struct Foo 70 { 71 @A("foo") 72 int i; 73 } 74 75 static assert(!hasUDA!(Foo, A)); 76 static assert(hasUDA!(Foo, e)); 77 static assert(hasUDA!(Foo.i, A)); 78 static assert(getUDA!(Foo.i, A).bar == "foo"); 79 80 //even UDA-Inception works :P 81 static assert(hasUDA!(getUDA!(Foo.i, A).bar, A)); 82 static assert(!hasUDA!(getUDA!(Foo.i, A).bar, e)); 83 }