3 回答
TA贡献1946条经验 获得超4个赞
可以发生包扩展的地方之一是在braced-init-list中。您可以通过将扩展放在虚拟数组的初始化列表中来利用此功能:
template<typename... Args>
static void foo2(Args &&... args)
{
int dummy[] = { 0, ( (void) bar(std::forward<Args>(args)), 0) ... };
}
要更详细地解释初始化程序的内容:
{ 0, ( (void) bar(std::forward<Args>(args)), 0) ... };
| | | | |
| | | | --- pack expand the whole thing
| | | |
| | --perfect forwarding --- comma operator
| |
| -- cast to void to ensure that regardless of bar()'s return type
| the built-in comma operator is used rather than an overloaded one
|
---ensure that the array has at least one element so that we don't try to make an
illegal 0-length array when args is empty
演示。
。
扩展的一个重要优势{}是它保证了从左到右的评估。
使用C ++ 17 折叠表达式,您只需编写即可
((void) bar(std::forward<Args>(args)), ...);
TA贡献1821条经验 获得超6个赞
参数包只能在严格定义的上下文列表中进行扩展,而运算符,
不是其中之一。换句话说,不可能使用包扩展来生成由运算符分隔的一系列子表达式组成的表达式,
。
经验法则是“扩展可以生成一个分隔模式列表,,
其中,
是一个列表分隔符。” 运算符,
不构造语法意义上的列表。
要为每个参数调用一个函数,可以使用递归(这是可变参数模板程序员框中的主要工具):
template <typename T>void bar(T t) {}void foo2() {}template <typename Car, typename... Cdr>void foo2(Car car, Cdr... cdr){ bar(car); foo2(cdr...);}int main(){ foo2 (1, 2, 3, "3");}
TA贡献1807条经验 获得超9个赞
参数包只能在严格定义的上下文列表中进行扩展,而运算符,
不是其中之一。换句话说,不可能使用包扩展来生成由运算符分隔的一系列子表达式组成的表达式,
。
经验法则是“扩展可以生成一个分隔,
模式列表,其中,
是一个列表分隔符。” 运算符,
不构造语法意义上的列表。
要为每个参数调用一个函数,可以使用递归(这是可变参数模板程序员框中的主要工具):
#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 ++中,说明&&
符可以表示两种内容之一:rvalue-references或通用引用。
我不会进入rvalue-references,而是进入使用可变参数模板的人; 普遍的参考是神的发送。
完美的转发
std::forward
通用引用的一个用途是将类型转换为其他函数。
在你的例子中,如果我们传递int&
给foo2
它,它会自动降级为int
因为foo2
模板扣除后生成的函数的签名,如果你想arg
将它转发给另一个通过引用修改它的函数,你将得到不希望的结果(变量将不会被更改)因为foo2
将传递一个引用传递int
给它创建的临时变量。为了解决这个问题,我们指定了一个转发函数来对变量(rvalue 或 lvalue)进行任何类型的引用。然后,为了确保我们传递了我们使用的转发函数中传递的确切类型,那么只有std::forward
那么我们是否允许降级类型; 因为我们现在处于最重要的地步。
如果您需要,请阅读有关通用引用和完美转发的更多信息 ; Scott Meyers作为一种资源非常棒。
- 3 回答
- 0 关注
- 832 浏览
添加回答
举报