问题出在TYPE var = args[c];,你为TYPE写什么?每个i 都有不同的类型,所以你不能像这样使用for 循环。
一般来说,正常的做法是使用递归。
void f() { } //end loop
template<class FirstType, typename...Args>
void f(FirstType&& first, Args&&...rest) {
//do loop body
loop_body(std::forward<FirstType>(first)...)
//do next "iteration"
f(std::forward<Args>(rest)...);
}
也有这种不用递归的方法,但是更高级一点:
template<typename...Args>
void f(Args&&...args) {
typedef int[] for_each;
for_each{((void)( loop_body(std::forward<Args>(args)) ),0)...,0};
}
最后,如果你真的想通过索引访问一个:
//note that "i" must be a compile time constant
auto var = std::get<i>(std::tie(std::forward<Args>(args)...));
typedef int[] 的代码很奇怪,所以我就放在这里。
我们想调用一个函数
loop_body(std::forward<Args>(args))...;,但不幸的是,参数包只能在某些上下文中扩展,而这不是其中之一。最简单和最明显的解决方案是将所有这些调用的结果传递给一个什么都不做的函数:
do_nothing(loop_body(std::forward<Args>(args))...),但不幸的是,这对于
void 返回类型失败,因为您无法实例化
void 以传递到
do_nothing。更糟糕的是,它可能会以错误的顺序调用每个函数。将
void 表达式“转换”为其他表达式的一种方法是使用逗号运算符
(func(), 0) 执行
func 然后“返回”
0。
更糟糕的是,出于我承认不理解的原因,
f(vs)...,0; 和
(f(vs),0)...,0; 是扩展参数包的有效上下文。但是,
type array[] = {vs...} 是一个有效的上下文。所以现在我们有一种方法可以将此上下文与具有返回值的表达式结合起来:
int array[] = {(f(vs),0)...}; 它可以工作!主要是!
如果参数包的类型为零(是的,这是有效的。永远不要忘记它。),那么这会导致编译器错误。所以我们必须在最后添加一个额外的零,所以总是至少有一个元素:
int array[] = {(f(vs),0)..., 0};。此外,大多数编译器警告
array 是一个未使用的变量。绕过该警告的一种方法是将类型设为临时类型。
int a = (expr); 是本地的,但
(int)(expr) 创建一个未命名的临时。所以我们想要
(int []){(f(vs),0)..., 0};。由于我不记得的原因,这个
(int[]) 通常隐藏在 typedef 后面。最后一点,由于某些类可以重载逗号运算符,因此将函数强制转换为
void 是最安全的:
int array[] = {((void)(f(vs)),0)..., 0};
不相关,我过去考虑过这个宏,它隐藏了更多丑陋的细节。但我觉得我忽略了一个缺点,否则它会更常见。
#define FOREACH_VARIADIC(EXPR) (int[]){((void)(EXPR),0)...,0}
template<typename...Args>
void f(Args&&...args) {
FOREACH_VARIADIC(loop_body(std::forward<Args>(args)));
}