Originariamente ho semplicemente risposto alla domanda, ma volevo ampliare questo aspetto per fornire una spiegazione più completa di come i pacchetti vengono espansi in cosa. Questo è il modo in cui penso comunque alle cose.
Qualsiasi pacchetto immediatamente seguito da un'ellissi è appena espanso. Quindi A<Ts...>
equivale a A<T1, T2, ..., TN>
e hun(vs...)
equivale allo stesso modo a hun(v1, v2, ..., vn)
. Dove diventa complicato è quando invece di un pacchetto seguito da ellissi ottieni qualcosa come ((expr)...)
. Questo verrà espanso in (expr1, expr2, ..., exprN)
dove expri
si riferisce all'espressione originale con qualsiasi pacchetto sostituito con la versione i
di esso. Quindi se avevi hun((vs+1)...)
, questo diventa hun(v1+1, v2+1, ..., vn+1)
. Dove diventa più divertente è che expr
può contenere più di un pacco (purché abbiano tutti la stessa dimensione!). Questo è il modo in cui implementiamo il modello di inoltro perfetto standard;
foo(std::forward<Args>(args)...)
Qui expr
contiene due confezioni (Args
e args
sono entrambi confezioni) e l'espansione "itera" oltre entrambi:
foo(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), ..., std::forward<ArgN>(argN));
Tale ragionamento dovrebbe rendere possibile camminare rapidamente attraverso i vostri casi per, dì, cosa succede quando chiami foo(1, 2, '3')
.
Il primo, gun(A<Ts...>::hun(vs)...);
espande Ts
"in luogo" e poi c'è un'espressione per espandere negli ultimi ellissi, quindi ciò richiede:
gun(A<int, int, char>::hun(1),
A<int, int, char>::hun(2),
A<int, int, char>::hun('3'));
Il secondo, gun(A<Ts...>::hun(vs...));
espande entrambi i pacchetti in luogo:
gun(A<int, int, char>::hun(1, 2, '3'));
il terzo, gun(A<Ts>::hun(vs)...)
, espande entrambi i pacchetti contemporaneamente:
gun(A<int>::hun(1),
A<int>::hun(2),
A<char>::hun('3'));
[update] Per completezza, gun(A<Ts>::hun(vs...)...)
chiamerebbe:
gun(A<int>::hun(1, 2, '3'),
A<int>::hun(1, 2, '3'),
A<char>::hun(1, 2, '3'));
Infine, c'è un ultimo caso di prendere in considerazione dove andiamo a mare sui puntini di sospensione:
gun(A<Ts...>::hun(vs...)...);
Questo non verrà compilato. Espandiamo sia Ts
sia vs
"in posizione", ma non abbiamo ancora alcun pacchetto da espandere per gli ellissi finali.
Divertimento con le pistole ?? – 0x499602D2
@ 0x499602D2 Fun gun, hun – chbaker0
Una domanda simile è questa http://stackoverflow.com/questions/17652412/what-are-the-rules-for-the-token-in-the-context-of-variadic- modello, ma le risposte qui sotto chiariscono in modo più approfondito la mia domanda, e sono più specifiche –