函子中的C ++ 11可变参数模板解压缩参数

蔡斯·刘易斯

我搞砸了可变参数的模板,并试图锻炼一个诱人的计划。我知道它们存在,但是只是想弄乱新功能。我正在使用VS2013试用版。我创建了一个仿函数类,该仿函数类包装了从C ++端调用lua函数所需的信息。但是,我无法终生获得将模板变量压入堆栈以进行解包和工作的模板函数。我已经尝试过在网上找到的每个示例,并尝试了他们提到如何解压缩功能模板的值的所有方法。我显然缺少了一些东西。我注意到的所有示例都引用了&&引用。这是一个要求吗?

/*
These functions push an item onto the lua stack
*/
template<typename T> inline void lua_push(lua_State* L,T&& t){ static_assert(false,      "Unsupported Type! Cannot set to lua stack"); }
template<> inline void lua_push<lua_CFunction>(lua_State* L,lua_CFunction&& func){      assert(L != nullptr && func != nullptr); lua_pushcfunction(L, func); }
template<> inline void lua_push<double>(lua_State* L,double&& d){ assert(L != nullptr);  lua_pushnumber(L, d); }
template<> inline void lua_push<int>(lua_State* L,int&& i){ assert(L != nullptr);  lua_pushinteger(L, i); }
template<> inline void lua_push<bool>(lua_State* L,bool&& b){ assert(L != nullptr);  lua_pushboolean(L, b); }
template<> inline void lua_push<std::string>(lua_State* L,std::string&& s){ assert(L != nullptr);  lua_pushlstring(L, s.c_str(), s.size()); }
template<> inline void lua_push<const char*>(lua_State* L,const char*&& s){ assert(L != nullptr); lua_pushstring(L, s); }

然后我想在本课中解压它

template<typename Return,typename... Args> class LuaFunctor{};
/*
    A Lua function that will return a single value.
*/
template<typename Return,typename... Args> class LuaFunctor<Return(Args...)>
{
private:
    //The lua state the function exists on
    lua_State* m_luaState;
    //Name of the function to be called in lua
    std::string m_FunctionName;
public:
    //Return typedef
    typedef Return return_type;
    //The number of arguments the functor accepts
    static const int arguments = sizeof...(Args);
    //Constructors
    inline LuaFunctor(lua_State* L,const std::string& name) : m_luaState(L), m_FunctionName(name) {}
    inline LuaFunctor(lua_State* L,const char* name) : m_luaState(L), m_FunctionName(name) {}
    //Function call overload that allows the functor to act like a function call of luascript
    inline Return operator()(Args&&... args)
    {
        //Assert that the function name does exist and luaState is pointing to something hopefully meaningful
        assert(m_luaState != nullptr && m_FunctionName.size() != 0);
        //Set the function
        lua_getglobal(m_luaState, m_FunctionName.c_str());
        //Verify Lua function is pushed onto the stack
        assert(lua_isfunction(m_luaState, -1));
        //If arguments exist push them onto the stack
        if (sizeof...(Args) != 0)
        {
                    /*
                      How do I unpack this?????
                      I want to unpack this into multiple functions
                      One for each type of argument.
                    */
            lua_push(m_luaState, std::forward<Args>(args))...; 
        }
        //Call the function that is in lua
        int status = lua_pcall(m_luaState, sizeof...(Args), 1, 0);
        /*
            If there was an error calling the function throw an exception
            TODO: parse the error using luas builtin decode of the error for now just pass it on
            TODO: create lua_exception
        */
        if (status != 0) throw std::exception("Error calling lua function");
        //Return the value request by lua, error checking is built-in to the function to verify type
        return lua_get<Return>(m_luaState);
    }
};
蔡斯·刘易斯

解决方法是这里。递归函数调用。尝试了我正在阅读的各种技巧,但这很简单。

/*
    These functions push an item onto the lua stack
*/
template<typename First, typename... Rest> inline void lua_push(lua_State* L,First first,Rest... rest)
{
    lua_push(L, first);
    lua_push(L, rest...);
}
template<typename T> inline void lua_push(lua_State* L, T t){ static_assert(false, "Invalid type attemptiing to be pushed onto lua stack!"); }
template<> inline void lua_push<lua_CFunction>(lua_State* L, lua_CFunction func){ assert(L != nullptr && func != nullptr); lua_pushcfunction(L, func); }
template<> inline void lua_push<double>(lua_State* L, double d){assert(L != nullptr);  lua_pushnumber(L, d); }
template<> inline void lua_push<int>(lua_State* L, int i){ assert(L != nullptr);  lua_pushinteger(L, i); }
template<> inline void lua_push<bool>(lua_State* L, bool b){ assert(L != nullptr);  lua_pushboolean(L, b); }
template<> inline void lua_push<std::string>(lua_State* L, std::string s){assert(L != nullptr);  lua_pushlstring(L, s.c_str(), s.size()); }
template<> inline void lua_push<const char*>(lua_State* L,const char* s){ assert(L != nullptr); lua_pushstring(L, s); }

该代码现在可以完美运行。

template<typename Return,typename... Args> class LuaFunctor<Return(Args...)>
{
private:
    //The lua state the function exists on
    lua_State* m_luaState;
    //Name of the function to be called in lua
    std::string m_FunctionName;
public:
    //Return typedef
    typedef Return return_type;
    //The number of arguments the functor accepts
    static const int arguments = sizeof...(Args);
    //Constructors
    inline LuaFunctor(lua_State* L,const std::string& name) : m_luaState(L), m_FunctionName(name) {}
    inline LuaFunctor(lua_State* L,const char* name) : m_luaState(L), m_FunctionName(name) {}
    //Function call overload that allows the functor to act like a function call of luascript
    inline Return operator()(Args... args)
    {
        //Assert that the function name does exist and luaState is pointing to something hopefully meaningful
        assert(m_luaState != nullptr && m_FunctionName.size() != 0);
        //Set the function
        lua_getglobal(m_luaState, m_FunctionName.c_str());
        //Verify Lua function is pushed onto the stack
        assert(lua_isfunction(m_luaState, -1));
        //If arguments exist push them onto the stack
        if (sizeof...(Args) != 0) lua_push(m_luaState, args...);
        //Call the function that is in lua
        int status = lua_pcall(m_luaState, sizeof...(Args), 1, 0);
        /*
            If there was an error calling the function throw an exception
            TODO: parse the error using luas builtin decode of the error for now just pass it on
            TODO: create lua_exception
        */
        if (status != 0)
        {
            report_errors(status);
            throw std::exception("Error calling lua function");
        }
        //Return the value request by lua, error checking is built-in to the function to verify type
        return lua_get<Return>(m_luaState);
    }
};

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

C ++可变参数模板打包到std :: array中并解压缩

来自分类Dev

如果可变参数模板解压缩中已达到终止功能,则异常

来自分类Dev

可变参数模板类型解压缩到地图键中

来自分类Dev

将可变参数模板参数解压缩到每种类型的数组应用函数中

来自分类Dev

c ++ 11递归可变参数模板

来自分类Dev

c ++ 11递归可变参数模板

来自分类Dev

可变参数模板中每个压缩参数的执行功能

来自分类Dev

可变参数模板将类型参数解压缩

来自分类Dev

可变参数模板将类型参数解压缩

来自分类Dev

C ++ 11中的可变参数模板和多重继承

来自分类Dev

C ++ 11可变参数模板和std :: endl

来自分类Dev

通过可变参数模板的C ++ 11构造函数继承

来自分类Dev

c ++ 11语法可变参数模板随rebind扩展

来自分类Dev

C ++ 11翻译可变参数模板以推断类类型

来自分类Dev

调用类内的函数的C ++ 11可变参数模板

来自分类Dev

(C ++ 11)可变参数模板序列打印

来自分类Dev

通过可变参数模板的C ++ 11构造函数继承

来自分类Dev

c ++ 11语法可变参数模板随rebind扩展

来自分类Dev

C ++ 11可变参数模板函数存储

来自分类Dev

C ++可变参数模板参数迭代

来自分类Dev

将功能参数的参数解压缩到C ++模板类

来自分类Dev

可变参数在go lang中打包和解压缩:'[] string {f(v)} ...'

来自分类Dev

decltype中的可变参数模板包

来自分类Dev

嵌套类中的可变参数模板

来自分类Dev

可变参数模板中的函数顺序

来自分类Dev

可变参数模板和C数组

来自分类Dev

C ++可变参数模板基础

来自分类Dev

C ++可变参数模板产品

来自分类Dev

C ++可变参数模板推导失败