作为模板参数,加上可变参数模板参数

Ral*_*ang 11 c++ c++11

我正在编写一个通用函数包装器,它可以将任何函数包装到具有该形式的lua样式调用中

int lua_function(lua_State*L)

我希望包装函数是即时生成的,所以我想将函数作为模板参数传递.如果你知道参数的数量(例如2),这是微不足道的:

template <typename R, typename Arg1, typename Arg2, R F(Arg1, Args)>
struct wrapper
Run Code Online (Sandbox Code Playgroud)

但是,我不知道这个数字,所以我请求variadic模板参数求助

// This won't work
template <typename R, typename... Args, R F(Args...)>
struct wrapper
Run Code Online (Sandbox Code Playgroud)

上面的内容不会编译,因为variadic参数必须是最后一个.所以我使用两个级别的模板,外部模板捕获类型,内部模板捕获函数:

template <typename R, typename... Args>
struct func_type<R(Args...)>
{
  // Inner function wrapper take the function pointer as a template argument
  template <R F(Args...)>
  struct func
  {
    static int call( lua_State *L )
    {
      // extract arguments from L
      F(/*arguments*/);
      return 1;
    }
  };
};
Run Code Online (Sandbox Code Playgroud)

这是有效的,除了包装像这样的函数

double sin(double d) {}
Run Code Online (Sandbox Code Playgroud)

用户必须写

func_type<decltype(sin)>::func<sin>::apply
Run Code Online (Sandbox Code Playgroud)

这很乏味.问题是:有没有更好的,用户友好的方式来做到这一点?(我不能用函数模板来包装整个东西,因为函数参数不能用作模板参数.)

Luc*_*ton 9

类似的事情std::functionstd::result_of使用以下技术来做你想要的变量模板:

template<typename Signature>
struct wrapper; // no base template

template<typename Ret, typename... Args>
struct wrapper<Ret(Args...)> {
    // instantiated for any function type
};
Run Code Online (Sandbox Code Playgroud)

你可以扩展上面的内容来添加一个非类型的Ret(&P)(Args...)模板参数(指向功能工作的指针),但你仍然需要decltype在用户级别,即wrapper<decltype(sin), sin>::apply.可以说,如果您决定使用宏来删除重复,那么它将是预处理器的合法使用.

template<typename Sig, Sig& S>
struct wrapper;

template<typename Ret, typename... Args, Ret(&P)(Args...)>
struct wrapper<Ret(Args...), P> {
    int
    static apply(lua_State*)
    {
        // pop arguments
        // Ret result = P(args...);
        // push result & return
        return 1;
    }
};

// &wrapper<decltype(sin), sin>::apply is your Lua-style wrapper function.
Run Code Online (Sandbox Code Playgroud)

以上编译与ideone的 gcc-4.5 .运行应用程序(可变地)弹出参数,祝你好运(如果你打开一个关于那个的问题,请给我留言).你考虑过使用Luabind吗?