SHAMELESS COPY [approved by its source]
参数包只能在严格定义的上下文列表中展开,运算符, 不是其中之一。换句话说,不可能使用包扩展来生成由一系列由运算符, 分隔的子表达式组成的表达式。
经验法则是“扩展可以生成, 分隔模式的列表,其中, 是列表分隔符。”运算符, 不构造语法意义上的列表。
要为每个参数调用一个函数,您可以使用递归(这是可变参数模板程序员的主要工具):
#include <utility>
template<typename T>
void foo(T &&t){}
template<typename Arg0, typename Arg1, typename ... Args>
void foo(Arg0 &&arg0, Arg1 &&arg1, Args &&... args){
foo(std::forward<Arg0>(arg0));
foo(std::forward<Arg1>(arg1), std::forward<Args>(args)...);
}
auto main() -> int{
foo(1, 2, 3, "3");
}
有用的非复制信息
您可能在此答案中没有看到的另一件事是使用&& 说明符和std::forward。在 C++ 中,&& 说明符可以表示以下两种情况之一:右值引用或通用引用。
我不会介绍右值引用,而是介绍使用可变参数模板的人;通用引用是天赐之物。
完美转发
std::forward 和通用引用的用途之一是将类型完美地转发给其他函数。
在您的示例中,如果我们将int& 传递给foo2,它将自动降级为int,因为模板扣除后生成的foo2 函数的签名,如果您想转发此@ 987654338@ 到另一个通过引用修改它的函数,你会得到不想要的结果(变量不会改变),因为foo2 将传递一个对通过传递一个int 给它创建的临时对象的引用。为了解决这个问题,我们指定了一个转发函数,以将任何类型的引用指向一个变量(右值或左值)。然后,为了确保我们传递在转发函数中传递的确切类型,我们使用std::forward,然后 only 然后我们是否允许降级类型;因为我们现在正处于最重要的阶段。
如果需要,请阅读 universal references 和 perfect forwarding 的更多信息; Scott Meyers 作为一种资源非常棒。