函数作为模板参数,加上可变参数模板参数 [英] functions as template argument, plus variadic template argument

查看:98
本文介绍了函数作为模板参数,加上可变参数模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写一个广义函数包装器,可以将任何函数包装成lua风格的调用,形式为

I'm writing a generalized function wrapper, that can wrap any function into a lua-style call, which has the form

int lua_function(lua_State * L)

int lua_function( lua_State *L)

我希望包装函数是即时生成的,所以我想把函数作为模板参数传递。如果你知道参数的数目(例如2),这很简单:

And I wish the wrapper function is generated on-the-fly, so I'm thinking of passing the function as a template argument. This is trivial if you know the number (e.g, 2) of arguments:

template <typename R, typename Arg1, typename Arg2, R F(Arg1, Args)>
struct wrapper

但是,我不知道数字,帮助的模板参数

However, I don't know the number, so I beg for variadic template argument for help

// This won't work
template <typename R, typename... Args, R F(Args...)>
struct wrapper

上述将不会编译,因为可变参数必须是最后一个一。所以我使用两个级别模板,外部模板捕获类型,内部模板捕获函数:

The above won't compile, since variadic argument has to be the last one. So I use two level template, the outer template captures types, the inner template captures the function:

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;
    }
  };
};

工作原理,除了包装像

double sin(double d) {}

用户必须写

func_type<decltype(sin)>::func<sin>::apply

这很乏味。
问题是:有什么更好的,用户友好的方式吗? (我不能使用函数模板来封装整个事物,coz一个函数参数不能用作模板参数。)

which is tedious. The question is: is there any better, user-friendlier way to do it? (I can't use a function template to wrap the whole thing, coz a function parameter can't be used as a template argument.)

推荐答案

std :: function std :: result_of 之类的东西使用以下技术关于可变参数模板:

Things like std::function and std::result_of use the following technique to do what you want regarding variadic templates:

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

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

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

You could expand the above to add a non-type Ret(&P)(Args...) template parameter (pointers to function work just as well) but you'd still need a decltype at the user level, i.e. wrapper<decltype(sin), sin>::apply. Arguably it would be a legitimate use of the preprocessor if you decide to use a macro to remove the repetition.

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.

以上编译与gcc-4.5在 ideone
运行应用程序的好运气(变化)弹出参数(如果你打开一个问题,给我留言)。你考虑过使用Luabind吗?

The above compiles with gcc-4.5 at ideone. Good luck with implementing the apply that (variadically) pops the arguments (leave me a comment if you open a question about that). Have you considered using Luabind?

这篇关于函数作为模板参数,加上可变参数模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆