Sq Plus Function Overloading
Last changed: -92.222.238.172

.

rochie

Summary

(Added to snapshot 05/27/07 kkawachi)

This enables squirrel script to call overloaded functions/constructors of C++.

The code consists of 2 patches and 1 new file (http://www.liebes-jahreshoroskop.com/).

Patch for "sqplus/sqplus.h":

diff -ur SQUIRREL2_1_0_sqplus_22/sqplus/sqplus.h SQUIRREL2_1_0_sqplus_22_OVERLOAD/sqplus/sqplus.h
--- SQUIRREL2_1_0_sqplus_22/sqplus/sqplus.h		2006-08-20 18:47:40.000000000 +0900
+++ SQUIRREL2_1_0_sqplus_22_OVERLOAD/sqplus/sqplus.h		2006-09-17 17:33:06.375000000 +0900
@@ -18,6 +18,7 @@
   #include <malloc.h>
 #endif
 #include <memory.h>
+#include <memory>
 #if defined(_MSC_VER) || defined(__BORLANDC__) 
   #include <tchar.h>
   #ifndef UNICODE
@@ -75,6 +76,10 @@
 // Define SQPLUS_CONST_OPT before including SqPlus.h for constant argument + constant member function support.
 //#define SQPLUS_CONST_OPT
 
+// === Function overloading support ===
+// Define SQPLUS_OVERLOAD_OPT before including SqPlus.h for function overloading support
+//#define SQPLUS_OVERLOAD_OPT
+
 // === Uncomment to support std::string ===
 //#define SQPLUS_SUPPORT_STD_STRING
 
@@ -585,6 +590,11 @@
 #include "SqPlusConst.h"
 #endif
 
+#ifdef SQPLUS_OVERLOAD_OPT
+#define SQPLUS_OVERLOAD_DECLARATION
+#include "SqPlusOverload.h"
+#endif
+ 
 //////////////////////////////////////////////////////////////////////////
 //////////// END Generalized Class/Struct Instance Support ///////////////
 //////////////////////////////////////////////////////////////////////////
@@ -1808,8 +1818,17 @@
       return *this;
   } // enumInt
 
+#ifdef SQPLUS_OVERLOAD_OPT
+#define SQPLUS_OVERLOAD_IMPLEMENTATION
+#include "SqPlusOverload.h"    
+#endif
 };
 
+#ifdef SQPLUS_OVERLOAD_OPT
+#define SQPLUS_OVERLOAD_FUNCTIONS
+#include "SqPlusOverload.h"    
+#endif
+
 // === BEGIN Function Call Handlers ===
 
 inline void Push(HSQUIRRELVM v,char value)           { sq_pushinteger(v,value); }

Patch for "testSqPlus2/testSqPlus2.cpp":

diff -ur SQUIRREL2_1_0_sqplus_22/testSqPlus2/testSqPlus2.cpp SQUIRREL2_1_0_sqplus_22_OVERLOAD/testSqPlus2/testSqPlus2.cpp
--- SQUIRREL2_1_0_sqplus_22/testSqPlus2/testSqPlus2.cpp		2006-06-27 10:18:10.000000000 +0900
+++ SQUIRREL2_1_0_sqplus_22_OVERLOAD/testSqPlus2/testSqPlus2.cpp		2006-09-17 17:33:19.546875000 +0900
@@ -8,6 +8,7 @@
 #include <stdarg.h> 
 #include <stdio.h>
 //#define SQPLUS_CONST_OPT
+//#define SQPLUS_OVERLOAD_OPT
 #include "sqplus.h"
 
 using namespace SqPlus;
@@ -30,6 +31,17 @@
   return _T("Returned String");
 }
 
+#ifdef SQPLUS_OVERLOAD_OPT
+void overloadTest(void) {scprintf(_T("void overloadTest(void)\n"));}
+void overloadTest(int) {scprintf(_T("void overloadTest(int)\n"));}
+void overloadTest(float) {scprintf(_T("void overloadTest(float)\n"));}
+
+static SQInteger releaseVector3(SQUserPointer up, SQInteger s) {
+  scprintf(_T("releaseVector3() called.\n"));
+  return 0;
+}
+#endif
+
 struct Vector3 {
   static float staticVar;
   float x,y,z;
@@ -48,6 +60,13 @@
   Vector3 operator+(Vector3 & v) {
     return Vector3(x+v.x,y+v.y,z+v.z);
   }
+#ifdef SQPLUS_OVERLOAD_OPT
+  void set(const Vector3 &src) {x = src.x; y = src.y; z = src.z;} 
+  float set(float xyz) {x = y = z = xyz; return xyz;}
+  void set(float x_, float y_, float z_) {x = x_; y = y_; z = z_;}
+  static void setStaticVar(void) {staticVar = 0.0;}
+  static void setStaticVar(float f) {staticVar = f;}
+#endif
 };
 
 
@@ -796,6 +815,17 @@
         func(&Vector3::operator+,_T("_add")).
         staticFunc(&Add2,_T("Add2")).
         staticFuncVarArgs(&Add,_T("Add")).
+# ifdef SQPLUS_OVERLOAD_OPT
+        overloadConstructor<Vector3(*)(void)>().
+        overloadConstructor<Vector3(*)(float, float, float)>().
+        overloadConstructor<Vector3(*)(Vector3&)>().
+        overloadFunc<void(Vector3::*)(const Vector3&)>(&Vector3::set, _T("set")).
+        overloadFunc<float(Vector3::*)(float)>(&Vector3::set, _T("set")).
+        overloadFunc<void(Vector3::*)(float, float, float)>(&Vector3::set, _T("set")).
+        overloadStaticFunc<void(*)(void)>(&Vector3::setStaticVar, _T("setStaticVar")).
+        overloadStaticFunc<void(*)(float)>(&Vector3::setStaticVar, _T("setStaticVar")).
+        releaseHook(&releaseVector3).
+# endif
 #if 1
         staticVar(&Vector3::staticVar,_T("staticVar")).
 #else
@@ -820,6 +850,12 @@
       BindConstant(SQ_10*2,_T("SQ_10_2"));
       BindConstant(_T("Global String"),_T("GLOBAL_STRING"));
 
+#ifdef SQPLUS_OVERLOAD_OPT
+      OverloadGlobal<void(*)(void)>(&overloadTest, _T("overloadTest"));
+      OverloadGlobal<void(*)(int)>(&overloadTest, _T("overloadTest"));
+      OverloadGlobal<void(*)(float)>(&overloadTest, _T("overloadTest"));
+#endif
+      
       SquirrelObject testStaticVars = SquirrelVM::CompileBuffer(_T(" local v = Vector3(); local v2 = Vector3(); local v3 = v+v2; v3 += v2; print(\"v3.x: \"+v3.x); print(\"Vector3::staticVar: \"+v.staticVar+\" Vector3::globalVar: \"+v.globalVar); v.staticVar = 0; "));
       SquirrelVM::RunScript(testStaticVars);
 
@@ -930,7 +966,35 @@
       SquirrelObject testRegV = SquirrelVM::CompileBuffer(_T(" local vec = Vector3(); print(vec.x); vec = vec.Add(vec); print(vec.x); vec = vec.Add(vec); print(vec.x); vec = vec.Add2(vec,vec); print(vec.x); local v2 = Vector3(); vec = v2.Inc(vec); print(vec.x); print(v2.x); "));
       SquirrelVM::RunScript(testRegV);
 
+#ifdef SQPLUS_OVERLOAD_OPT
+      SquirrelObject testOverload = SquirrelVM::CompileBuffer(
+          _T(" print(\"=== BEGIN OVERLOAD ===\");")
+          _T(" local vec3v = Vector3();")
+          _T(" print(\"constructed by void: \" + vec3v.x + \" \" + vec3v.y + \" \" + vec3v.z);")
+          _T(" local vec3f = Vector3(-11.0, 22.0, -33.0);")
+          _T(" print(\"constructed by 3 floats: \" + vec3f.x + \" \" + vec3f.y + \" \" + vec3f.z);")
+          _T(" local vec3c = Vector3(vec3f);")
+          _T(" print(\"constructed by copy: \" + vec3c.x + \" \" + vec3c.y + \" \" + vec3c.z);")
+          _T(" vec3v.set(333.0);")
+          _T(" print(\"modified by set(float): \" + vec3v.x + \" \" + vec3v.y + \" \" + vec3v.z);")
+          _T(" vec3v.set(444.0, 555.0, 666.0);")
+          _T(" print(\"modified by set(float, float, float): \" + vec3v.x + \" \" + vec3v.y + \" \" + vec3v.z);")
+          _T(" vec3v.set(vec3f);")
+          _T(" print(\"modified by set(Vector3&): \" + vec3v.x + \" \" + vec3v.y + \" \" + vec3v.z);")
+          _T(" vec3v.setStaticVar();")
+          _T(" print(\"staticVar: \" + vec3c.staticVar);")
+          _T(" vec3f.setStaticVar(2.0);")
+          _T(" print(\"staticVar: \" + vec3c.staticVar);")
+          _T(" overloadTest();")
+          _T(" overloadTest(100);")
+          _T(" overloadTest(2.0);")
+          _T(" print(\"=== END OVERLOAD ===\");")
+            );
+      SquirrelVM::RunScript(testOverload);
+#endif
 
+      
+      
 #ifdef SQ_USE_CLASS_INHERITANCE
       SquirrelObject testReg0 = SquirrelVM::CompileBuffer(_T(" co <- CustomTestObj(\"hello\",123,true); co.varArgTypes(\"str\",123,123,\"str\"); co.varArgTypes(123,\"str\",\"str\",123); "));
       SquirrelVM::RunScript(testReg0);
Files SQUIRREL2_1_0_sqplus_22/testSqPlus2/testSqPlus2.exe and SQUIRREL2_1_0_sqplus_22_OVERLOAD/testSqPlus2/testSqPlus2.exe differ

New File "sqplus/SqPlusOverload.h":

// SqPlusOverload.h
// SqPlus function overloading support created by Katsuaki Kawachi.

#ifdef SQPLUS_OVERLOAD_DECLARATION
#undef SQPLUS_OVERLOAD_DECLARATION

template<typename Func> struct Arg;

#endif // SQPLUS_OVERLOAD_DECLARATION


#ifdef SQPLUS_OVERLOAD_IMPLEMENTATION
#undef SQPLUS_OVERLOAD_IMPLEMENTATION
private:
    class SQFuncHolder {
    private:
        template<typename T>
        class FlexArray {
        protected:
            SquirrelObject array;
        public:
            FlexArray(int size = 0) {
                this->resize(size);
            }
            int size(void) const {
                return array.Len();
            }
            void resize(int newSize) {
                if (this->size() == 0) {
                    array = SquirrelVM::CreateArray(newSize);
                } else {
                    array.ArrayResize(newSize);
                }
            }
            void push_back(const T &t) {
                this->set(this->size(), t);
            }
            void set(int index, const T &t) {
                get(index) = t;
            }
            T &get(int index) {
                if (index >= array.Len()) {
                    resize(index + 1);
                }
                SQUserPointer up = array.GetUserPointer(index);
                if (!up) {
                    up = sq_newuserdata(SquirrelVM::GetVMPtr(), sizeof(T));
                    new(static_cast<T*>(up)) T;
                    array.SetUserPointer(index, up);
                }
                return *static_cast<T*>(up);
            }
        };
        /*
          storage of wrapped C++ functions
         */
        typedef SQInteger(*WrappedFunction)(HSQUIRRELVM, bool, int);
        typedef FlexArray<WrappedFunction> SQWrappedFuncArray;
        typedef FlexArray<SQWrappedFuncArray> SQWrappedFuncArray2 ;
        typedef FlexArray<SQWrappedFuncArray2> SQWrappedFuncArray3 ;

        struct MemberHolder {
            static SQWrappedFuncArray &funcs(int functionIndex,
                                             int paramCount) {
                static SQWrappedFuncArray3 funcs;
                return funcs.get(paramCount).get(functionIndex);
            }
        };
        struct StaticHolder {
            static SQWrappedFuncArray &funcs(int functionIndex,
                                             int paramCount) {
                static SQWrappedFuncArray3 funcs;
                return funcs.get(paramCount).get(functionIndex);
            }
        };
        struct ConstructorHolder {
            static SQWrappedFuncArray &funcs(int paramCount) {
                static SQWrappedFuncArray2 funcs;
                return funcs.get(paramCount);
            }
        };
            
        /*
          wrapper for C++ functions
         */
        template<typename Mfunc> struct MemberDispatcher {
            static inline FlexArray<Mfunc> &mfunc(void) {
                static FlexArray<Mfunc> mfunc;
                return mfunc;
            }
            static inline SQInteger
            dispatch(HSQUIRRELVM v, bool execute, int functionIndex) {
                return execute ?
                    Call(*GetInstance<TClassType, true>(v, 1),
                         mfunc().get(functionIndex), v, 2) :
                    Arg<Mfunc>::argTypeDistance(v);
            }
        };
        template<typename Sfunc> struct StaticDispatcher {
            static inline FlexArray<Sfunc> &sfunc(void) {
                static FlexArray<Sfunc> sfunc;
                return sfunc;
            }
            static inline SQInteger
            dispatch(HSQUIRRELVM v, bool execute, int functionIndex) {
                return execute ?
                    Call(sfunc().get(functionIndex), v, 2) :
                    Arg<Sfunc>::argTypeDistance(v);
            }
        };
        template<typename Cfunc> struct Constructor {
            static inline Cfunc &cfunc(void) {
                static Cfunc cfunc = 0;
                return cfunc;
            }
            static inline SQInteger
            construct(HSQUIRRELVM v, bool execute, int) {
                return execute ?
                    Call(cfunc(), v, 2) :
                    Arg<Cfunc>::argTypeDistance(v);
            }
        };

        // search and call an overloaded function on runtime
        static inline SQInteger
        call(SQWrappedFuncArray &funcs, HSQUIRRELVM v, int functionIndex = 0) {
            bool ambiguous = false;
            int imin = -1;
            int dmin = INT_MAX;
            for (int i = 0, size = funcs.size(); i < size; ++i) {
                const int d = (**funcs.get(i))(v, false, functionIndex);
                if (d == 0) { // complete match
                    imin = i;
                    ambiguous = false;
                    goto SQPLUS_OVERLOAD_CALL_IMMEDIATE_EXECUTION;
                } else if (0 < d && d < dmin) {
                    dmin = d;
                    imin = i;
                    ambiguous = false;
                } else if (d == dmin) {
                    ambiguous = true;
                }
            }

            if (ambiguous) {
                return sq_throwerror(v, _T("Call of overloaded function")
                                     _T(" is ambiguous"));
            } else if (imin == -1) {
                return sq_throwerror(v, _T("No match for given arguments"));
            }

          SQPLUS_OVERLOAD_CALL_IMMEDIATE_EXECUTION:
            return (**funcs.get(imin))(v, true, functionIndex);
        }
        
    public:
        template<typename Mfunc> static inline void
        addMemberFunc(int functionIndex, Mfunc mfunc) {
            MemberHolder::funcs(functionIndex, Arg<Mfunc>::num()).push_back(
                &MemberDispatcher<Mfunc>::dispatch
                );
            MemberDispatcher<Mfunc>::mfunc().set(functionIndex, mfunc);
        }
        template<typename Sfunc> static inline void
        addStaticFunc(int functionIndex, Sfunc sfunc) {
            StaticHolder::funcs(functionIndex, Arg<Sfunc>::num()).push_back(
                &StaticDispatcher<Sfunc>::dispatch
                );
            StaticDispatcher<Sfunc>::sfunc().set(functionIndex, sfunc);
        }
        template<typename Cfunc> static inline void
        addConstructor(Cfunc cfunc) {
            ConstructorHolder::funcs(Arg<Cfunc>::num()).push_back(
                &Constructor<Cfunc>::construct
                );
            Constructor<Cfunc>::cfunc() = cfunc;
        }
            
        static inline SQInteger
        memberCall(int paramCount, HSQUIRRELVM v, int functionIndex) {
            return call(MemberHolder::funcs(functionIndex, paramCount),
                        v, functionIndex);
        }
        static inline SQInteger
        staticCall(int paramCount, HSQUIRRELVM v, int functionIndex) {
            return call(StaticHolder::funcs(functionIndex, paramCount),
                        v, functionIndex);
        }
        static inline SQInteger
        constructorCall(int paramCount, HSQUIRRELVM v, int) {
            return call(ConstructorHolder::funcs(paramCount), v);
        }
    }; // class SQFuncHolder


    struct FunctionNameEnumerator {
        SquirrelObject names;
        FunctionNameEnumerator(void) : names(SquirrelVM::CreateTable()) {}
        int index(const SQChar *n) {
            int i;
            SquirrelObject v = names.GetValue(n);
            if (v.IsNull()) {
                i = names.Len();
                names.SetValue(n, i);
            } else {
                i = v.ToInteger();
            }
            return i;
        }
    };
    FunctionNameEnumerator overloadedMemberNames;
    FunctionNameEnumerator overloadedStaticMemberNames;

    template<typename Func>
    class SQOverloader {
    private:
        static inline int &functionIndex(void) {
            static int index;
            return index;
        }
        
        static inline SQInteger switcher(HSQUIRRELVM v,
                                         int(*caller)(int, HSQUIRRELVM, int)) {
            return (*caller)(StackHandler(v).GetParamCount() - 1,
                             v,
                             functionIndex());
        }
        
        static inline SQInteger memberSwitcher(HSQUIRRELVM v) {
            return switcher(v, SQFuncHolder::memberCall);
        }
        static inline SQInteger staticSwitcher(HSQUIRRELVM v) {
            return switcher(v, SQFuncHolder::staticCall);
        }
        static inline SQInteger constructorSwitcher(HSQUIRRELVM v) {
            return switcher(v, SQFuncHolder::constructorCall);
        }
        
    public:
        static inline void addMemberFunc(SQClassDef<TClassType> *def,
                                         Func mfunc,
                                         const SQChar *name) {
            functionIndex() = def->overloadedMemberNames.index(name);
            SQFuncHolder::addMemberFunc(functionIndex(), mfunc);
            def->staticFuncVarArgs(memberSwitcher, name);
        }
        static inline void addStaticFunc(SQClassDef<TClassType> *def,
                                         Func sfunc,
                                         const SQChar *name) {
            functionIndex() = def->overloadedStaticMemberNames.index(name);
            SQFuncHolder::addStaticFunc(functionIndex(), sfunc);
            def->staticFuncVarArgs(staticSwitcher, name);
        }
        template<typename Cfunc>
        static inline void addConstructor(SQClassDef<TClassType> *def,
                                          Cfunc cfunc) {
            SQFuncHolder::addConstructor(cfunc);
            def->staticFuncVarArgs(constructorSwitcher, _T("constructor"));
        }
        static inline void addGlobalFunc(SQClassDef<TClassType> *def,
                                         Func gfunc,
                                         const SQChar *name) {
            functionIndex() = def->overloadedStaticMemberNames.index(name);
            SQFuncHolder::addStaticFunc(functionIndex(), gfunc);
            SquirrelVM::CreateFunctionGlobal(staticSwitcher, name, _T("*"));
        }
    };

    static inline SQRELEASEHOOK &release(void) {
        static SQRELEASEHOOK hook = ReleaseClassPtr<TClassType>::release;
        return hook;
    }

public:
    template<typename Mfunc>
    SQClassDef<TClassType> &overloadFunc(Mfunc mfunc, const SQChar *n) {
        SQOverloader<Mfunc>::addMemberFunc(this, mfunc, n);
        return *this;
    }
    template<typename Sfunc>
    SQClassDef<TClassType> &overloadStaticFunc(Sfunc sfunc, const SQChar *n) {
        SQOverloader<Sfunc>::addStaticFunc(this, sfunc, n);
        return *this;
    }
    template<typename Cmetafunc>
    SQClassDef<TClassType> &overloadConstructor(void) {
        SQOverloader<Cmetafunc>::addConstructor(this, &Arg<Cmetafunc>::create);
        return *this;
    }
    template<typename Cfunc>
    SQClassDef<TClassType> &overloadConstructor(Cfunc cfunc) {
        SQOverloader<Cfunc>::addConstructor(this, cfunc);
        return *this;
    }
    template<typename Gfunc>
    SQClassDef<TClassType> &overloadGlobalFunc(Gfunc gfunc, const SQChar *n) {
        SQOverloader<Gfunc>::addGlobalFunc(this, gfunc, n);
        return *this;
    }

    SQClassDef<TClassType> &releaseHook(SQRELEASEHOOK releaseHook) {
        release() = releaseHook;
        return *this;
    }
    static inline SQRELEASEHOOK &getReleaseHook(void) {
        return release();
    }


#endif // SQPLUS_OVERLOAD_IMPLEMENTATION



#ifdef SQPLUS_OVERLOAD_FUNCTIONS
#undef SQPLUS_OVERLOAD_FUNCTIONS

struct GlobalFuncOverloader {};
static inline SQClassDef<GlobalFuncOverloader> &globalFuncOverloader(void)
{
    static SQClassDef<GlobalFuncOverloader> ffo(_T("GlobalFuncOverloader"));
    return ffo;
}

template<typename Gfunc> void
OverloadGlobal(Gfunc gfunc, const SQChar *n)
{
    globalFuncOverloader().overloadGlobalFunc(gfunc, n);
}

template<typename TYPE> struct CheckInstance {
    template<typename T> struct unref {typedef T type;};
    template<typename T> struct unref<T&> {typedef T type;};
    template<typename T> struct unref<T*> {typedef T type;};
    template<typename T> struct unref<const T&> {typedef T type;};
    template<typename T> struct unref<const T*> {typedef T type;};
    
    /*
      d = -1 : not in hierarchy
      d = 0  : same
      d > 0  : similar (o is d-th subclass of TYPE)
    */
    static inline int distance(HSQUIRRELVM v, int index) {
        HSQOBJECT o;
        sq_resetobject(&o);
        sq_getstackobj(v, index, &o);
    
        const int top = sq_gettop(v);
        sq_pushroottable(v);

        // Check plain object type
        int d = -1;
        if (Match(TypeWrapper<TYPE>(), v, index)) {
            d = 0;
            
            // Check instance type hierarchy
            if (sq_type(o) == OT_INSTANCE) {
                SQUserPointer dsttype =
                    ClassType<typename unref<TYPE>::type>::type();
            
                SQUserPointer argtype;
                for (sq_getclass(v, index);
                     sq_gettypetag(v, -1, &argtype) == SQ_OK;
                     sq_getbase(v, -1)) {
                    if (argtype == dsttype) {
                        goto SQPLUS_OVERLOAD_DISTANCE_IMMEDIATE_RETURN;
                    }
                    ++d;
                }
                d = -1;         // no matching type found
            }
        }
      SQPLUS_OVERLOAD_DISTANCE_IMMEDIATE_RETURN:
        sq_settop(v, top);
        return d;
    }
};


template<typename T, typename R>
struct Arg<R(T::*)(void)> {
    static inline int num(void) {return 0;}
    static inline int argTypeDistance(HSQUIRRELVM) {
        return 0;
    }
};

template<typename T, typename R, typename A1>
struct Arg<R(T::*)(A1)> {
    static inline int num(void) {return 1;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        return Arg<R(*)(A1)>::argTypeDistance(v);
    }
};

template<typename T, typename R, typename A1, typename A2>
struct Arg<R(T::*)(A1, A2)> {
    static inline int num(void) {return 2;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        return Arg<R(*)(A1, A2)>::argTypeDistance(v);
    }
};

template<typename T, typename R, typename A1, typename A2, typename A3>
struct Arg<R(T::*)(A1, A2, A3)> {
    static inline int num(void) {return 3;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        return Arg<R(*)(A1, A2, A3)>::argTypeDistance(v);
    }
};

template<typename T, typename R, typename A1, typename A2, typename A3, typename A4>
struct Arg<R(T::*)(A1, A2, A3, A4)> {
    static inline int num(void) {return 4;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        return Arg<R(*)(A1, A2, A3, A4)>::argTypeDistance(v);
    }
};

template<typename T, typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
struct Arg<R(T::*)(A1, A2, A3, A4, A5)> {
    static inline int num(void) {return 5;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        return Arg<R(*)(A1, A2, A3, A4, A5)>::argTypeDistance(v);
    }
};

template<typename T, typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
struct Arg<R(T::*)(A1, A2, A3, A4, A5, A6)> {
    static inline int num(void) {return 6;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        return Arg<R(*)(A1, A2, A3, A4, A5, A6)>::argTypeDistance(v);
    }
};

template<typename T, typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
struct Arg<R(T::*)(A1, A2, A3, A4, A5, A6, A7)> {
    static inline int num(void) {return 7;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        return Arg<R(*)(A1, A2, A3, A4, A5, A6, A7)>::argTypeDistance(v);
    }
};

static inline int classAllocationError(HSQUIRRELVM v) {
    return sq_throwerror(v, _T("Failed to allocate memory"));
}

template<typename R>
struct Arg<R(*)(void)> {
    static inline int num(void) {return 0;}
    static inline int argTypeDistance(HSQUIRRELVM) {return 0;}
    static inline int create(void) {
        HSQUIRRELVM v = SquirrelVM::GetVMPtr();
        R *r = static_cast<R*>(sq_malloc(sizeof(R)));
        return r ?
            PostConstruct<R>(v, new(r) R,
                             SQClassDef<R>::getReleaseHook()) :
            classAllocationError(v);
    }
};

template<typename R, typename A1>
struct Arg<R(*)(A1)> {
    static inline int num(void) {return 1;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        int s, r;
        r = 0;
        s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
        return r;
    }
    static inline int create(A1 a1) {
        HSQUIRRELVM v = SquirrelVM::GetVMPtr();
        R *r = static_cast<R*>(sq_malloc(sizeof(R)));
        return r ?
            PostConstruct<R>(v, new(r) R(a1),
                             SQClassDef<R>::getReleaseHook()) :
            classAllocationError(v);
    }
};

template<typename R, typename A1, typename A2>
struct Arg<R(*)(A1, A2)> {
    static inline int num(void) {return 2;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        int s, r;
        r = 0;
        s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
        return r;
    }
    static inline int create(A1 a1, A2 a2) {
        HSQUIRRELVM v = SquirrelVM::GetVMPtr();
        R *r = static_cast<R*>(sq_malloc(sizeof(R)));
        return r ?
            PostConstruct<R>(v, new(r) R(a1, a2),
                             SQClassDef<R>::getReleaseHook()) :
            classAllocationError(v);
    }
};

template<typename R, typename A1, typename A2, typename A3>
struct Arg<R(*)(A1, A2, A3)> {
    static inline int num(void) {return 3;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        int s, r;
        r = 0;
        s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A3>::distance(v, 4); if (s < 0) {return -1;} r += s;
        return r;
    }
    static inline int create(A1 a1, A2 a2, A3 a3) {
        HSQUIRRELVM v = SquirrelVM::GetVMPtr();
        R *r = static_cast<R*>(sq_malloc(sizeof(R)));
        return r ?
            PostConstruct<R>(v, new(r) R(a1, a2, a3),
                             SQClassDef<R>::getReleaseHook()) :
            classAllocationError(v);
    }
};

template<typename R, typename A1, typename A2, typename A3, typename A4>
struct Arg<R(*)(A1, A2, A3, A4)> {
    static inline int num(void) {return 4;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        int s, r;
        r = 0;
        s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A3>::distance(v, 4); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A4>::distance(v, 5); if (s < 0) {return -1;} r += s;
        return r;
    }
    static inline int create(A1 a1, A2 a2, A3 a3, A4 a4) {
        HSQUIRRELVM v = SquirrelVM::GetVMPtr();
        R *r = static_cast<R*>(sq_malloc(sizeof(R)));
        return r ?
            PostConstruct<R>(v, new(r) R(a1, a2, a3, a4),
                             SQClassDef<R>::getReleaseHook()) :
            classAllocationError(v);
    }
};

template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
struct Arg<R(*)(A1, A2, A3, A4, A5)> {
    static inline int num(void) {return 5;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        int s, r;
        r = 0;
        s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A3>::distance(v, 4); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A4>::distance(v, 5); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A5>::distance(v, 6); if (s < 0) {return -1;} r += s;
        return r;
    }
    static inline int create(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
        HSQUIRRELVM v = SquirrelVM::GetVMPtr();
        R *r = static_cast<R*>(sq_malloc(sizeof(R)));
        return r ?
            PostConstruct<R>(v, new(r) R(a1, a2, a3, a4, a5),
                             SQClassDef<R>::getReleaseHook()) :
            classAllocationError(v);
    }
};

template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
struct Arg<R(*)(A1, A2, A3, A4, A5, A6)> {
    static inline int num(void) {return 6;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        int s, r;
        r = 0;
        s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A3>::distance(v, 4); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A4>::distance(v, 5); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A5>::distance(v, 6); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A6>::distance(v, 7); if (s < 0) {return -1;} r += s;
        return r;
    }
    static inline int create(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
        HSQUIRRELVM v = SquirrelVM::GetVMPtr();
        R *r = static_cast<R*>(sq_malloc(sizeof(R)));
        return r ?
            PostConstruct<R>(v, new(r) R(a1, a2, a3, a4, a5, a6),
                             SQClassDef<R>::getReleaseHook()) :
            classAllocationError(v);
    }
};

template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
struct Arg<R(*)(A1, A2, A3, A4, A5, A6, A7)> {
    static inline int num(void) {return 7;}
    static inline int argTypeDistance(HSQUIRRELVM v) {
        int s, r;
        r = 0;
        s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A3>::distance(v, 4); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A4>::distance(v, 5); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A5>::distance(v, 6); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A6>::distance(v, 7); if (s < 0) {return -1;} r += s;
        s = CheckInstance<A7>::distance(v, 8); if (s < 0) {return -1;} r += s;
        return r;
    }
    static inline int create(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
        HSQUIRRELVM v = SquirrelVM::GetVMPtr();
        R *r = static_cast<R*>(sq_malloc(sizeof(R)));
        return r ?
            PostConstruct<R>(v, new(r) R(a1, a2, a3, a4, a5, a6, a7),
                             SQClassDef<R>::getReleaseHook()) :
            classAllocationError(v);
    }
};
#endif // SQPLUS_OVERLOAD_FUNCTIONS

// SqPlusOverload.h

// Local Variables: 
// mode: c++
// End: