使用可变模板解包参数列表

5
我正在尝试创建一个C++便利包装器,用于一个使用不透明数据类型的旧C API。其中有一个特定的C函数,它使用C的<stdarg.h>工具接受格式字符串以及可变数量的参数。作为我的包装器的一部分,我想能够向该函数传递任意数量的参数(包括C++对象)。然而,由于显然<stdarg.h>工具无法处理非POD数据,因此我创建了一个模板转换函数,将C++对象(如std::string)转换为POD等效项。
我认为使用C++0x可变模板应该是一个简单的练习,但我很难想出如何编写这个函数,以便在将我的转换函数应用于每个参数时正确展开参数包。
我目前的进展是:
   template <class T, class... Args>
   void apply(OPAQUE* object, const char* fmt_string, T&& val, Args&&... args)
   {
      apply(object, fmt_string, Convert(val), args...);
   }

   template <class... Args>
   void apply(OPAQUE* object, const char* fmt_string, Args&&... args)
   {
      C_API_Function_Call(object, fmt_string, args...);
   }

当然,这样做是不起作用的,因为递归函数调用从未实际解包Args...,因此它会一直递归直到堆栈溢出。我无法想象如何在传递当前参数给Convert函数的同时解包参数并递归传递结果。有没有什么办法可以做到这一点?
2个回答

26

我认为你需要与您进行完美转发时相同的语法:

template <class... Args>
void apply(OPAQUE* object, const char* fmt_string, Args&&... args)
{
   C_API_Function_Call(object, fmt_string, Convert(std::forward<Arg>(args))...);
}

省略号(...)可以放置在包含参数组的表达式右侧,而不仅仅是直接放置在参数组本身的右侧。

因此:
func(args...) 会扩展为 func(arg1, arg2, arg3, [...] , argN)
func(args)... 会扩展为 func(arg1), func(arg2), [...] , func(argN)


2
不确定为什么提问者还没有改变他的看法并接受这个答案。目前被接受的答案显然是错误的,而您的答案是正确的。+1 乾杯! - Johannes Schaub - litb

-1

目前C++0x草案没有提供任何解决方案。因为问题类似于扩展元组,您可以阅读此讨论并编写类似的扩展函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接