Add a generic collection of class templates to ADT for building
[oota-llvm.git] / include / llvm / ADT / VariadicFunction.h
1 //===--- VariadicFunctions.h - Variadic Functions ---------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements compile-time type-safe variadic functions.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ADT_VARIADIC_FUNCTION_H
15 #define LLVM_ADT_VARIADIC_FUNCTION_H
16
17 #include "llvm/ADT/ArrayRef.h"
18
19 namespace llvm {
20
21 // Define macros to aid in expanding a comma separated series with the index of
22 // the series pasted onto the last token.
23 #define LLVM_COMMA_JOIN1(x) x ## 0
24 #define LLVM_COMMA_JOIN2(x) LLVM_COMMA_JOIN1(x), x ## 1
25 #define LLVM_COMMA_JOIN3(x) LLVM_COMMA_JOIN2(x), x ## 2
26 #define LLVM_COMMA_JOIN4(x) LLVM_COMMA_JOIN3(x), x ## 3
27 #define LLVM_COMMA_JOIN5(x) LLVM_COMMA_JOIN4(x), x ## 4
28 #define LLVM_COMMA_JOIN6(x) LLVM_COMMA_JOIN5(x), x ## 5
29 #define LLVM_COMMA_JOIN7(x) LLVM_COMMA_JOIN6(x), x ## 6
30 #define LLVM_COMMA_JOIN8(x) LLVM_COMMA_JOIN7(x), x ## 7
31 #define LLVM_COMMA_JOIN9(x) LLVM_COMMA_JOIN8(x), x ## 8
32 #define LLVM_COMMA_JOIN10(x) LLVM_COMMA_JOIN9(x), x ## 9
33 #define LLVM_COMMA_JOIN11(x) LLVM_COMMA_JOIN10(x), x ## 10
34 #define LLVM_COMMA_JOIN12(x) LLVM_COMMA_JOIN11(x), x ## 11
35 #define LLVM_COMMA_JOIN13(x) LLVM_COMMA_JOIN12(x), x ## 12
36 #define LLVM_COMMA_JOIN14(x) LLVM_COMMA_JOIN13(x), x ## 13
37 #define LLVM_COMMA_JOIN15(x) LLVM_COMMA_JOIN14(x), x ## 14
38 #define LLVM_COMMA_JOIN16(x) LLVM_COMMA_JOIN15(x), x ## 15
39 #define LLVM_COMMA_JOIN17(x) LLVM_COMMA_JOIN16(x), x ## 16
40 #define LLVM_COMMA_JOIN18(x) LLVM_COMMA_JOIN17(x), x ## 17
41 #define LLVM_COMMA_JOIN19(x) LLVM_COMMA_JOIN18(x), x ## 18
42 #define LLVM_COMMA_JOIN20(x) LLVM_COMMA_JOIN19(x), x ## 19
43 #define LLVM_COMMA_JOIN21(x) LLVM_COMMA_JOIN20(x), x ## 20
44 #define LLVM_COMMA_JOIN22(x) LLVM_COMMA_JOIN21(x), x ## 21
45 #define LLVM_COMMA_JOIN23(x) LLVM_COMMA_JOIN22(x), x ## 22
46 #define LLVM_COMMA_JOIN24(x) LLVM_COMMA_JOIN23(x), x ## 23
47 #define LLVM_COMMA_JOIN25(x) LLVM_COMMA_JOIN24(x), x ## 24
48 #define LLVM_COMMA_JOIN26(x) LLVM_COMMA_JOIN25(x), x ## 25
49 #define LLVM_COMMA_JOIN27(x) LLVM_COMMA_JOIN26(x), x ## 26
50 #define LLVM_COMMA_JOIN28(x) LLVM_COMMA_JOIN27(x), x ## 27
51 #define LLVM_COMMA_JOIN29(x) LLVM_COMMA_JOIN28(x), x ## 28
52 #define LLVM_COMMA_JOIN30(x) LLVM_COMMA_JOIN29(x), x ## 29
53 #define LLVM_COMMA_JOIN31(x) LLVM_COMMA_JOIN30(x), x ## 30
54 #define LLVM_COMMA_JOIN32(x) LLVM_COMMA_JOIN31(x), x ## 31
55
56 /// \brief Class which can simulate a type-safe variadic function.
57 ///
58 /// The VariadicFunction class template makes it easy to define
59 /// type-safe variadic functions where all arguments have the same
60 /// type.
61 ///
62 /// Suppose we need a variadic function like this:
63 ///
64 ///   ResultT Foo(const ArgT &A_0, const ArgT &A_1, ..., const ArgT &A_N);
65 ///
66 /// Instead of many overloads of Foo(), we only need to define a helper
67 /// function that takes an array of arguments:
68 ///
69 ///   ResultT FooImpl(ArrayRef<const ArgT *> Args) {
70 ///     // 'Args[i]' is a pointer to the i-th argument passed to Foo().
71 ///     ...
72 ///   }
73 ///
74 /// and then define Foo() like this:
75 ///
76 ///   const VariadicFunction<ResultT, ArgT, FooImpl> Foo;
77 ///
78 /// VariadicFunction takes care of defining the overloads of Foo().
79 ///
80 /// Actually, Foo is a function object (i.e. functor) instead of a plain
81 /// function.  This object is stateless and its constructor/destructor
82 /// does nothing, so it's safe to create global objects and call Foo(...) at
83 /// any time.
84 ///
85 /// Sometimes we need a variadic function to have some fixed leading
86 /// arguments whose types may be different from that of the optional
87 /// arguments.  For example:
88 ///
89 ///   bool FullMatch(const StringRef &S, const RE &Regex,
90 ///                  const ArgT &A_0, ..., const ArgT &A_N);
91 ///
92 /// VariadicFunctionN is for such cases, where N is the number of fixed
93 /// arguments.  It is like VariadicFunction, except that it takes N more
94 /// template arguments for the types of the fixed arguments:
95 ///
96 ///   bool FullMatchImpl(const StringRef &S, const RE &Regex,
97 ///                      ArrayRef<const ArgT *> Args) { ... }
98 ///   const VariadicFunction2<bool, const StringRef&,
99 ///                           const RE&, ArgT, FullMatchImpl>
100 ///       FullMatch;
101 ///
102 /// Currently VariadicFunction and friends support up-to 3
103 /// fixed leading arguments and up-to 32 optional arguments.
104 template <typename ResultT, typename ArgT,
105           ResultT (*Func)(ArrayRef<const ArgT *>)>
106 class VariadicFunction {
107  public:
108   VariadicFunction() {}
109
110   ResultT operator()() const {
111     return Func(ArrayRef<const ArgT *>());
112   }
113
114 #define LLVM_DEFINE_OVERLOAD(N) \
115   ResultT operator()(LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
116     const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
117     return Func(Args); \
118   }
119   LLVM_DEFINE_OVERLOAD(1)
120   LLVM_DEFINE_OVERLOAD(2)
121   LLVM_DEFINE_OVERLOAD(3)
122   LLVM_DEFINE_OVERLOAD(4)
123   LLVM_DEFINE_OVERLOAD(5)
124   LLVM_DEFINE_OVERLOAD(6)
125   LLVM_DEFINE_OVERLOAD(7)
126   LLVM_DEFINE_OVERLOAD(8)
127   LLVM_DEFINE_OVERLOAD(9)
128   LLVM_DEFINE_OVERLOAD(10)
129   LLVM_DEFINE_OVERLOAD(11)
130   LLVM_DEFINE_OVERLOAD(12)
131   LLVM_DEFINE_OVERLOAD(13)
132   LLVM_DEFINE_OVERLOAD(14)
133   LLVM_DEFINE_OVERLOAD(15)
134   LLVM_DEFINE_OVERLOAD(16)
135   LLVM_DEFINE_OVERLOAD(17)
136   LLVM_DEFINE_OVERLOAD(18)
137   LLVM_DEFINE_OVERLOAD(19)
138   LLVM_DEFINE_OVERLOAD(20)
139   LLVM_DEFINE_OVERLOAD(21)
140   LLVM_DEFINE_OVERLOAD(22)
141   LLVM_DEFINE_OVERLOAD(23)
142   LLVM_DEFINE_OVERLOAD(24)
143   LLVM_DEFINE_OVERLOAD(25)
144   LLVM_DEFINE_OVERLOAD(26)
145   LLVM_DEFINE_OVERLOAD(27)
146   LLVM_DEFINE_OVERLOAD(28)
147   LLVM_DEFINE_OVERLOAD(29)
148   LLVM_DEFINE_OVERLOAD(30)
149   LLVM_DEFINE_OVERLOAD(31)
150   LLVM_DEFINE_OVERLOAD(32)
151 #undef LLVM_DEFINE_OVERLOAD
152 };
153
154 template <typename ResultT, typename Param0T, typename ArgT,
155           ResultT (*Func)(Param0T, ArrayRef<const ArgT *>)>
156 class VariadicFunction1 {
157  public:
158   VariadicFunction1() {}
159
160   ResultT operator()(Param0T P0) const {
161     return Func(P0, ArrayRef<const ArgT *>());
162   }
163
164 #define LLVM_DEFINE_OVERLOAD(N) \
165   ResultT operator()(Param0T P0, LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
166     const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
167     return Func(P0, Args); \
168   }
169   LLVM_DEFINE_OVERLOAD(1)
170   LLVM_DEFINE_OVERLOAD(2)
171   LLVM_DEFINE_OVERLOAD(3)
172   LLVM_DEFINE_OVERLOAD(4)
173   LLVM_DEFINE_OVERLOAD(5)
174   LLVM_DEFINE_OVERLOAD(6)
175   LLVM_DEFINE_OVERLOAD(7)
176   LLVM_DEFINE_OVERLOAD(8)
177   LLVM_DEFINE_OVERLOAD(9)
178   LLVM_DEFINE_OVERLOAD(10)
179   LLVM_DEFINE_OVERLOAD(11)
180   LLVM_DEFINE_OVERLOAD(12)
181   LLVM_DEFINE_OVERLOAD(13)
182   LLVM_DEFINE_OVERLOAD(14)
183   LLVM_DEFINE_OVERLOAD(15)
184   LLVM_DEFINE_OVERLOAD(16)
185   LLVM_DEFINE_OVERLOAD(17)
186   LLVM_DEFINE_OVERLOAD(18)
187   LLVM_DEFINE_OVERLOAD(19)
188   LLVM_DEFINE_OVERLOAD(20)
189   LLVM_DEFINE_OVERLOAD(21)
190   LLVM_DEFINE_OVERLOAD(22)
191   LLVM_DEFINE_OVERLOAD(23)
192   LLVM_DEFINE_OVERLOAD(24)
193   LLVM_DEFINE_OVERLOAD(25)
194   LLVM_DEFINE_OVERLOAD(26)
195   LLVM_DEFINE_OVERLOAD(27)
196   LLVM_DEFINE_OVERLOAD(28)
197   LLVM_DEFINE_OVERLOAD(29)
198   LLVM_DEFINE_OVERLOAD(30)
199   LLVM_DEFINE_OVERLOAD(31)
200   LLVM_DEFINE_OVERLOAD(32)
201 #undef LLVM_DEFINE_OVERLOAD
202 };
203
204 template <typename ResultT, typename Param0T, typename Param1T, typename ArgT,
205           ResultT (*Func)(Param0T, Param1T, ArrayRef<const ArgT *>)>
206 class VariadicFunction2 {
207  public:
208   VariadicFunction2() {}
209
210   ResultT operator()(Param0T P0, Param1T P1) const {
211     return Func(P0, P1, ArrayRef<const ArgT *>());
212   }
213
214 #define LLVM_DEFINE_OVERLOAD(N) \
215   ResultT operator()(Param0T P0, Param1T P1, \
216                      LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
217     const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
218     return Func(P0, P1, Args); \
219   }
220   LLVM_DEFINE_OVERLOAD(1)
221   LLVM_DEFINE_OVERLOAD(2)
222   LLVM_DEFINE_OVERLOAD(3)
223   LLVM_DEFINE_OVERLOAD(4)
224   LLVM_DEFINE_OVERLOAD(5)
225   LLVM_DEFINE_OVERLOAD(6)
226   LLVM_DEFINE_OVERLOAD(7)
227   LLVM_DEFINE_OVERLOAD(8)
228   LLVM_DEFINE_OVERLOAD(9)
229   LLVM_DEFINE_OVERLOAD(10)
230   LLVM_DEFINE_OVERLOAD(11)
231   LLVM_DEFINE_OVERLOAD(12)
232   LLVM_DEFINE_OVERLOAD(13)
233   LLVM_DEFINE_OVERLOAD(14)
234   LLVM_DEFINE_OVERLOAD(15)
235   LLVM_DEFINE_OVERLOAD(16)
236   LLVM_DEFINE_OVERLOAD(17)
237   LLVM_DEFINE_OVERLOAD(18)
238   LLVM_DEFINE_OVERLOAD(19)
239   LLVM_DEFINE_OVERLOAD(20)
240   LLVM_DEFINE_OVERLOAD(21)
241   LLVM_DEFINE_OVERLOAD(22)
242   LLVM_DEFINE_OVERLOAD(23)
243   LLVM_DEFINE_OVERLOAD(24)
244   LLVM_DEFINE_OVERLOAD(25)
245   LLVM_DEFINE_OVERLOAD(26)
246   LLVM_DEFINE_OVERLOAD(27)
247   LLVM_DEFINE_OVERLOAD(28)
248   LLVM_DEFINE_OVERLOAD(29)
249   LLVM_DEFINE_OVERLOAD(30)
250   LLVM_DEFINE_OVERLOAD(31)
251   LLVM_DEFINE_OVERLOAD(32)
252 #undef LLVM_DEFINE_OVERLOAD
253 };
254
255 template <typename ResultT, typename Param0T, typename Param1T,
256           typename Param2T, typename ArgT,
257           ResultT (*Func)(Param0T, Param1T, Param2T, ArrayRef<const ArgT *>)>
258 class VariadicFunction3 {
259  public:
260   VariadicFunction3() {}
261
262   ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const {
263     return Func(P0, P1, P2, ArrayRef<const ArgT *>());
264   }
265
266 #define LLVM_DEFINE_OVERLOAD(N) \
267   ResultT operator()(Param0T P0, Param1T P1, Param2T P2, \
268                      LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
269     const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
270     return Func(P0, P1, P2, Args); \
271   }
272   LLVM_DEFINE_OVERLOAD(1)
273   LLVM_DEFINE_OVERLOAD(2)
274   LLVM_DEFINE_OVERLOAD(3)
275   LLVM_DEFINE_OVERLOAD(4)
276   LLVM_DEFINE_OVERLOAD(5)
277   LLVM_DEFINE_OVERLOAD(6)
278   LLVM_DEFINE_OVERLOAD(7)
279   LLVM_DEFINE_OVERLOAD(8)
280   LLVM_DEFINE_OVERLOAD(9)
281   LLVM_DEFINE_OVERLOAD(10)
282   LLVM_DEFINE_OVERLOAD(11)
283   LLVM_DEFINE_OVERLOAD(12)
284   LLVM_DEFINE_OVERLOAD(13)
285   LLVM_DEFINE_OVERLOAD(14)
286   LLVM_DEFINE_OVERLOAD(15)
287   LLVM_DEFINE_OVERLOAD(16)
288   LLVM_DEFINE_OVERLOAD(17)
289   LLVM_DEFINE_OVERLOAD(18)
290   LLVM_DEFINE_OVERLOAD(19)
291   LLVM_DEFINE_OVERLOAD(20)
292   LLVM_DEFINE_OVERLOAD(21)
293   LLVM_DEFINE_OVERLOAD(22)
294   LLVM_DEFINE_OVERLOAD(23)
295   LLVM_DEFINE_OVERLOAD(24)
296   LLVM_DEFINE_OVERLOAD(25)
297   LLVM_DEFINE_OVERLOAD(26)
298   LLVM_DEFINE_OVERLOAD(27)
299   LLVM_DEFINE_OVERLOAD(28)
300   LLVM_DEFINE_OVERLOAD(29)
301   LLVM_DEFINE_OVERLOAD(30)
302   LLVM_DEFINE_OVERLOAD(31)
303   LLVM_DEFINE_OVERLOAD(32)
304 #undef LLVM_DEFINE_OVERLOAD
305 };
306
307 // Cleanup the macro namespace.
308 #undef LLVM_COMMA_JOIN1
309 #undef LLVM_COMMA_JOIN2
310 #undef LLVM_COMMA_JOIN3
311 #undef LLVM_COMMA_JOIN4
312 #undef LLVM_COMMA_JOIN5
313 #undef LLVM_COMMA_JOIN6
314 #undef LLVM_COMMA_JOIN7
315 #undef LLVM_COMMA_JOIN8
316 #undef LLVM_COMMA_JOIN9
317 #undef LLVM_COMMA_JOIN10
318 #undef LLVM_COMMA_JOIN11
319 #undef LLVM_COMMA_JOIN12
320 #undef LLVM_COMMA_JOIN13
321 #undef LLVM_COMMA_JOIN14
322 #undef LLVM_COMMA_JOIN15
323 #undef LLVM_COMMA_JOIN16
324 #undef LLVM_COMMA_JOIN17
325 #undef LLVM_COMMA_JOIN18
326 #undef LLVM_COMMA_JOIN19
327 #undef LLVM_COMMA_JOIN20
328 #undef LLVM_COMMA_JOIN21
329 #undef LLVM_COMMA_JOIN22
330 #undef LLVM_COMMA_JOIN23
331 #undef LLVM_COMMA_JOIN24
332 #undef LLVM_COMMA_JOIN25
333 #undef LLVM_COMMA_JOIN26
334 #undef LLVM_COMMA_JOIN27
335 #undef LLVM_COMMA_JOIN28
336 #undef LLVM_COMMA_JOIN29
337 #undef LLVM_COMMA_JOIN30
338 #undef LLVM_COMMA_JOIN31
339 #undef LLVM_COMMA_JOIN32
340
341 } // end namespace llvm
342
343 #endif  // LLVM_ADT_VARIADIC_FUNCTION_H