Variadic模板包扩展

时间:2012-02-07 19:05:34

标签: c++ parameters c++11 variadic-templates

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)...);
}

2 个答案:

答案 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)...中,列表中的每个成员TsUsVs(在锁定步骤中枚举)将被替换为该模式,并将形成逗号分隔列表:

   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),它将扩展为v1v2等等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")
       );
}