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
.