// Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Copyright 2005-2010 Google, Inc. // Author: jpr@google.com (Jake Ratkiewicz) // Convenience templates for defining arg packs for the FstClass operations. // See operation-templates.h for a discussion about why these are needed; the // short story is that all FstClass operations must be implemented by a version // that takes one argument, most likely a struct bundling all the // logical arguments together. These template structs provide convenient ways // to specify these bundles (e.g. by means of appropriate typedefs). // The ArgPack template is sufficient for bundling together all the args for // a particular function. The function is assumed to be void-returning. If // you want a space for a return value, use the WithReturnValue template // as follows: // WithReturnValue<bool, ArgPack<...> > #ifndef FST_SCRIPT_ARG_PACKS_H_ #define FST_SCRIPT_ARG_PACKS_H_ namespace fst { namespace script { namespace args { // Sentinel value that means "no arg here." class none_type { }; // Base arg pack template class. Specializations follow that allow // fewer numbers of arguments (down to 2). If the maximum number of arguments // increases, you will need to change three things: // 1) Add more template parameters to this template // 2) Add more specializations to allow fewer numbers of parameters than // the new max. // 3) Add extra none_types to all existing specializations to fill // the new slots. // 9 args (max) template<class T1, class T2 = none_type, class T3 = none_type, class T4 = none_type, class T5 = none_type, class T6 = none_type, class T7 = none_type, class T8 = none_type, class T9 = none_type> struct Package { T1 arg1; T2 arg2; T3 arg3; T4 arg4; T5 arg5; T6 arg6; T7 arg7; T8 arg8; T9 arg9; Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) : arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5), arg6(arg6), arg7(arg7), arg8(arg8), arg9(arg9) { } }; // 8 args template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> struct Package<T1, T2, T3, T4, T5, T6, T7, T8, none_type> { T1 arg1; T2 arg2; T3 arg3; T4 arg4; T5 arg5; T6 arg6; T7 arg7; T8 arg8; Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) : arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5), arg6(arg6), arg7(arg7), arg8(arg8) { } }; // 7 args template<class T1, class T2, class T3, class T4, class T5, class T6, class T7> struct Package<T1, T2, T3, T4, T5, T6, T7, none_type, none_type> { T1 arg1; T2 arg2; T3 arg3; T4 arg4; T5 arg5; T6 arg6; T7 arg7; Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) : arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5), arg6(arg6), arg7(arg7) { } }; // 6 args template<class T1, class T2, class T3, class T4, class T5, class T6> struct Package<T1, T2, T3, T4, T5, T6, none_type, none_type, none_type> { T1 arg1; T2 arg2; T3 arg3; T4 arg4; T5 arg5; T6 arg6; Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) : arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5), arg6(arg6) { } }; // 5 args template<class T1, class T2, class T3, class T4, class T5> struct Package<T1, T2, T3, T4, T5, none_type, none_type, none_type, none_type> { T1 arg1; T2 arg2; T3 arg3; T4 arg4; T5 arg5; Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) : arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5) { } }; // 4 args template<class T1, class T2, class T3, class T4> struct Package<T1, T2, T3, T4, none_type, none_type, none_type, none_type, none_type> { T1 arg1; T2 arg2; T3 arg3; T4 arg4; Package(T1 arg1, T2 arg2, T3 arg3, T4 arg4) : arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4) { } }; // 3 args template<class T1, class T2, class T3> struct Package<T1, T2, T3, none_type, none_type, none_type, none_type, none_type, none_type> { T1 arg1; T2 arg2; T3 arg3; Package(T1 arg1, T2 arg2, T3 arg3) : arg1(arg1), arg2(arg2), arg3(arg3) { } }; // 2 args (minimum) template<class T1, class T2> struct Package<T1, T2, none_type, none_type, none_type, none_type, none_type, none_type, none_type> { T1 arg1; T2 arg2; Package(T1 arg1, T2 arg2) : arg1(arg1), arg2(arg2) { } }; // Tack this on to an existing arg pack to add a return value. // The syntax for accessing the args is then slightly more stilted, // as you must do an extra member access (since the args are stored // as a member of this class). // The alternative is to declare another slew of templates for functions // that return a value, analogous to the above. template<class Retval, class ArgPackage> struct WithReturnValue { Retval retval; const ArgPackage &args; explicit WithReturnValue(const ArgPackage &args) : args(args) { } }; // We don't want to store a reference to a reference, if ArgPackage is // already some reference type. template<class Retval, class ArgPackage> struct WithReturnValue<Retval, ArgPackage&> { Retval retval; const ArgPackage &args; explicit WithReturnValue(const ArgPackage &args) : args(args) { } }; } // namespace args } // namespace script } // namespace fst #endif // FST_SCRIPT_ARG_PACKS_H_