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))
Esto debería ser obvio.
3.
gun(A<Ts>::hun(vs)...)
=> gun(A<T1>::hun(v1), A<T2>::hun(v2), …, A<Tn>::hun(vn))
(En este caso el programa no se compilará si las longitudes de Ts y VS difieren)
El ...
habrá expandido un patrón (que incluye paquetes de parámetros) precediéndola, lo que significa que. En foo(Ts, Us, Vs)...
, cada miembro de la lista Ts
, Us
, Vs
(enumerados en el paso de bloqueo) será subsituted en ese patrón, y se forma una lista coma:
foo(Ts, Us, Vs)...
=> foo(T1, U1, V1), foo(T2, U2, V2), …, foo(Tn, Un, Vn)
y si hay expansiones anidada, los patrones más íntimos se expandirá primero. Por lo tanto, en el caso 1, el patrón Ts
se expandirá primero en T1, T2, …, Tn
. Y luego, el patrón que precede al externo ...
es A<T1, T2, …, Tn>::fun(vs)
- tenga en cuenta que Ts
se ha expandido, por lo que se expandirá a A<T1, T2, …, Tn>::fun(v1), <T1, T2, …, Tn>::fun(v2), …, <T1, T2, …, Tn>::fun(vm)
sustituyendo v1
, v2
, etc. en vs
.
es probable que desee especificar que 'Ts' es (por ejemplo)' void *, int, char, std :: string' o algo así, por lo que las respuestas alinear un poco mejor. –