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

时间:2011-05-16 11:38:43

标签: c++ c++11

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

int lua_function(lua_State * L)

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

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

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

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

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

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

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

2 个答案:

答案 0 :(得分:9)

答案 1 :(得分:0)

正如@Juraj在评论中所说,函数指针可以是模板参数,请参阅以下简单示例:

#include <iostream>
#include <boost/typeof/typeof.hpp>

void f(int b, double c, std::string const& g)
{
  std::cout << "f(): " << g << std::endl;
}

template <typename F, F* addr>
struct wrapper
{
  void operator()()
  {
    std::string bar("bar");
    (*addr)(1, 10., bar);
  }  
};

int main(void)
{
  wrapper<BOOST_TYPEOF(f), &f> w;
  w();
  return 0;
}

工作版:http://www.ideone.com/LP0TO

我正在使用BOOST_TYPEOF,因为我总是在当前标准中提供示例,但它与decltype类似。这就是你追求的目标吗?