可变模板包扩展

问题描述 投票:0回答:2

Andrei 在 GoingNative 2012 上的演讲中,他谈到了可变参数模板,并一度通过下面的示例解释了参数包扩展的工作原理。作为这个主题的新手,我发现很难理解每种情况的工作原理,有人可以解释一下扩展在

gun
的每个函数调用中是如何工作的吗?

template<class... Ts> void fun(Ts... vs) {
    gun(A<Ts...>::hun(vs)...);
    gun(A<Ts...>::hun(vs...));
    gun(A<Ts>::hun(vs)...);
}
c++ c++11 parameters variadic-templates pack-expansion
2个回答
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
。 .


5
投票

KennyTM的回答很完美。我也喜欢样品。但由于他的答案很抽象,我不认为在他的答案中添加演示是正确的事情。所以他的答案的演示就在这里。我假设他的答案是正确的,我自己一无所知。 (如果你支持这个,也支持他)

显然这都是伪代码,只是显示扩展状态。

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")
       );
}
© www.soinside.com 2019 - 2024. All rights reserved.