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 
35 namespace fst {
36 namespace script {
37 namespace args {
38 
39 // Sentinel value that means "no arg here."
40 class 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)
53 template<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>
62 struct 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 
PackagePackage73   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
80 template<class T1,
81          class T2,
82          class T3,
83          class T4,
84          class T5,
85          class T6,
86          class T7,
87          class T8>
88 struct 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
105 template<class T1,
106          class T2,
107          class T3,
108          class T4,
109          class T5,
110          class T6,
111          class T7>
112 struct 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
129 template<class T1,
130          class T2,
131          class T3,
132          class T4,
133          class T5,
134          class T6>
135 struct 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
150 template<class T1,
151          class T2,
152          class T3,
153          class T4,
154          class T5>
155 struct 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
168 template<class T1,
169          class T2,
170          class T3,
171          class T4>
172 struct 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
184 template<class T1,
185          class T2,
186          class T3>
187 struct 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)
199 template<class T1,
200          class T2>
201 struct 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 
218 template<class Retval, class ArgPackage>
219 struct 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.
228 template<class Retval, class ArgPackage>
229 struct 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