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 }