1
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6//     http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13//
14// Copyright 2005-2010 Google, Inc.
15// Author: jpr@google.com (Jake Ratkiewicz)
16
17// Convenience templates for defining arg packs for the FstClass operations.
18
19// See operation-templates.h for a discussion about why these are needed; the
20// short story is that all FstClass operations must be implemented by a version
21// that takes one argument, most likely a struct bundling all the
22// logical arguments together. These template structs provide convenient ways
23// to specify these bundles (e.g. by means of appropriate typedefs).
24
25// The ArgPack template is sufficient for bundling together all the args for
26// a particular function. The function is assumed to be void-returning. If
27// you want a space for a return value, use the WithReturnValue template
28// as follows:
29
30// WithReturnValue<bool, ArgPack<...> >
31
32#ifndef FST_SCRIPT_ARG_PACKS_H_
33#define FST_SCRIPT_ARG_PACKS_H_
34
35namespace fst {
36namespace script {
37namespace args {
38
39// Sentinel value that means "no arg here."
40class none_type { };
41
42// Base arg pack template class. Specializations follow that allow
43// fewer numbers of arguments (down to 2). If the maximum number of arguments
44// increases, you will need to change three things:
45//   1) Add more template parameters to this template
46//   2) Add more specializations to allow fewer numbers of parameters than
47//      the new max.
48//   3) Add extra none_types to all existing specializations to fill
49//      the new slots.
50
51
52// 9 args (max)
53template<class T1,
54         class T2 = none_type,
55         class T3 = none_type,
56         class T4 = none_type,
57         class T5 = none_type,
58         class T6 = none_type,
59         class T7 = none_type,
60         class T8 = none_type,
61         class T9 = none_type>
62struct Package {
63  T1 arg1;
64  T2 arg2;
65  T3 arg3;
66  T4 arg4;
67  T5 arg5;
68  T6 arg6;
69  T7 arg7;
70  T8 arg8;
71  T9 arg9;
72
73  Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6,
74          T7 arg7, T8 arg8, T9 arg9) :
75      arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5),
76      arg6(arg6), arg7(arg7), arg8(arg8), arg9(arg9) { }
77};
78
79// 8 args
80template<class T1,
81         class T2,
82         class T3,
83         class T4,
84         class T5,
85         class T6,
86         class T7,
87         class T8>
88struct Package<T1, T2, T3, T4, T5, T6, T7, T8, none_type> {
89  T1 arg1;
90  T2 arg2;
91  T3 arg3;
92  T4 arg4;
93  T5 arg5;
94  T6 arg6;
95  T7 arg7;
96  T8 arg8;
97
98  Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6,
99          T7 arg7, T8 arg8) :
100      arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5),
101      arg6(arg6), arg7(arg7), arg8(arg8) { }
102};
103
104// 7 args
105template<class T1,
106         class T2,
107         class T3,
108         class T4,
109         class T5,
110         class T6,
111         class T7>
112struct Package<T1, T2, T3, T4, T5, T6, T7,
113               none_type, none_type> {
114  T1 arg1;
115  T2 arg2;
116  T3 arg3;
117  T4 arg4;
118  T5 arg5;
119  T6 arg6;
120  T7 arg7;
121
122  Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6,
123          T7 arg7) :
124      arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5),
125      arg6(arg6), arg7(arg7) { }
126};
127
128// 6 args
129template<class T1,
130         class T2,
131         class T3,
132         class T4,
133         class T5,
134         class T6>
135struct Package<T1, T2, T3, T4, T5, T6, none_type,
136               none_type, none_type> {
137  T1 arg1;
138  T2 arg2;
139  T3 arg3;
140  T4 arg4;
141  T5 arg5;
142  T6 arg6;
143
144  Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) :
145      arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5),
146      arg6(arg6) { }
147};
148
149// 5 args
150template<class T1,
151         class T2,
152         class T3,
153         class T4,
154         class T5>
155struct Package<T1, T2, T3, T4, T5, none_type, none_type,
156               none_type, none_type> {
157  T1 arg1;
158  T2 arg2;
159  T3 arg3;
160  T4 arg4;
161  T5 arg5;
162
163  Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) :
164      arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5) { }
165};
166
167// 4 args
168template<class T1,
169         class T2,
170         class T3,
171         class T4>
172struct Package<T1, T2, T3, T4, none_type, none_type,
173               none_type, none_type, none_type> {
174  T1 arg1;
175  T2 arg2;
176  T3 arg3;
177  T4 arg4;
178
179  Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4) :
180      arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4) { }
181};
182
183// 3 args
184template<class T1,
185         class T2,
186         class T3>
187struct Package<T1, T2, T3, none_type, none_type,
188               none_type, none_type, none_type,
189               none_type> {
190  T1 arg1;
191  T2 arg2;
192  T3 arg3;
193
194  Package(T1 arg1, T2 arg2, T3 arg3) :
195      arg1(arg1), arg2(arg2), arg3(arg3) { }
196};
197
198// 2 args (minimum)
199template<class T1,
200         class T2>
201struct Package<T1, T2, none_type, none_type,
202               none_type, none_type, none_type,
203               none_type, none_type> {
204  T1 arg1;
205  T2 arg2;
206
207  Package(T1 arg1, T2 arg2) :
208      arg1(arg1), arg2(arg2) { }
209};
210
211// Tack this on to an existing arg pack to add a return value.
212// The syntax for accessing the args is then slightly more stilted,
213// as you must do an extra member access (since the args are stored
214// as a member of this class).
215// The alternative is to declare another slew of templates for functions
216// that return a value, analogous to the above.
217
218template<class Retval, class ArgPackage>
219struct WithReturnValue {
220  Retval retval;
221  const ArgPackage &args;
222
223  explicit WithReturnValue(const ArgPackage &args) : args(args) { }
224};
225
226// We don't want to store a reference to a reference, if ArgPackage is
227// already some reference type.
228template<class Retval, class ArgPackage>
229struct WithReturnValue<Retval, ArgPackage&> {
230  Retval retval;
231  const ArgPackage &args;
232
233  explicit WithReturnValue(const ArgPackage &args) : args(args) { }
234};
235
236}  // namespace args
237}  // namespace script
238}  // namespace fst
239
240#endif  // FST_SCRIPT_ARG_PACKS_H_
241