在Andrei's talk on GoingNative 2012中,他讨论了Variadic模板,并且他在一个方面解释了参数包扩展如何工作的示例。作为这个主题的新手,我发现很难理解每个案例的工作原理,有人可以解释一下扩展在gun
的每个函数调用中是如何工作的吗?
template<class... Ts> void fun(Ts... vs) {
gun(A<Ts...>::hun(vs)...);
gun(A<Ts...>::hun(vs...));
gun(A<Ts>::hun(vs)...);
}
答案 0 :(得分:10)
1
gun(A<Ts...>::hun(vs)...)
=> gun(A<T1, T2, …, Tn>::hun(vs)...)
=> gun(A<T1, T2, …, Tn>::hun(v1),
A<T1, T2, …, Tn>::hun(v2),
…,
A<T1, T2, …, Tn>::hun(vm))
2
gun(A<Ts...>::hun(vs...))
=> gun(A<T1, T2, …, Tn>::hun(vs...))
=> gun(A<T1, T2, …, Tn>::hun(v1, v2, …, vm))
这应该是显而易见的。
3
gun(A<Ts>::hun(vs)...)
=> gun(A<T1>::hun(v1), A<T2>::hun(v2), …, A<Tn>::hun(vn))
(在这种情况下,如果Ts和vs的长度不同,程序将无法编译)
...
将展开其前面的模式(包括任何参数包),这意味着在foo(Ts, Us, Vs)...
中,列表中的每个成员Ts
,Us
, Vs
(在锁定步骤中枚举)将被替换为该模式,并将形成逗号分隔列表:
foo(Ts, Us, Vs)...
=> foo(T1, U1, V1), foo(T2, U2, V2), …, foo(Tn, Un, Vn)
如果存在嵌套扩展,则最内层的模式将首先展开。因此,在案例1中,模式Ts
将首先扩展为T1, T2, …, Tn
。然后,外部...
之前的模式为A<T1, T2, …, Tn>::fun(vs)
- 请注意Ts
已展开 - 因此,通过替换A<T1, T2, …, Tn>::fun(v1), A<T1, T2, …, Tn>::fun(v2), …, A<T1, T2, …, Tn>::fun(vm)
,它将扩展为v1
, v2
等等vs
。
答案 1 :(得分:5)
KennyTM的答案是完美的。我也喜欢样品。但由于他的答案是抽象的,我不觉得在他的答案中添加演示是正确的。所以他的答案的演示就在这里。我假设他的回答是正确的,我自己一无所知。 (如果你赞成这一点,也可以投票支持他)
显然,这只是显示扩展状态的所有psudocode。
void foo<void*,int,char,std::string>(nullptr, 32, '7', "BANANA") {
//gun(A<Ts...>::hun(vs)...);
gun(A<void*,int,char,std::string>::hun(nullptr)
,A<void*,int,char,std::string>::hun(32)
,A<void*,int,char,std::string>::hun('7')
,A<void*,int,char,std::string>::hun("BANANA")
);
//gun(A<Ts...>::hun(vs...));
gun(A<void*,int,char,std::string>::hun(nullptr, 32, '7', "BANANA");
//gun(A<Ts>::hun(vs)...);
gun(A<void*>::hun(nullptr)
,A<int>::hun(32),
,A<char>::hun('7'),
,A<std::string>::hun("BANANA")
);
}