prima un po 'di codice, poi alcuni contesto, allora la domanda:variadic alias template come argomenti di template
template <typename T> using id = T;
template <template <typename...> class F, typename... T>
using apply1 = F <T...>;
template <template <typename...> class F>
struct apply2
{
template <typename... T>
using map = F <T...>;
};
// ...
cout << apply1 <id, int>() << endl;
cout << apply2 <id>::map <int>() << endl;
Sia clang 3.3 e gcc 4.8.1 compilare questo senza errori, applicando il metafunction identità int
, così sia le espressioni restituiscono un valore predefinito int
(zero).
Il fatto che id
è un po 'template <typename>
apply1
, apply2
si aspettano un template <typename...>
fatto mi riguardano, in primo luogo. Tuttavia, è abbastanza comodo che questo esempio funziona perché altrimenti METAFUNCTIONS come apply1
, apply2
dovrebbero essere molto più coinvolti.
D'altro canto, tali alias del modello causano seri problemi nel codice reale che non riesco a riprodurre qui: errori interni del compilatore frequenti per gcc e comportamento inaspettato meno frequente per clang (solo nei test SFINAE più avanzati).
Dopo mesi di tentativi ed errori, io ora installare e provare il codice a (sperimentale) gcc 4.9.0, ed ecco che arriva l'errore:
test.cpp: In instantiation of ‘struct apply2<id>’:
test.cpp:17:22: error: pack expansion argument for non-pack parameter ‘T’ of alias template ‘template<class T> using id = T’
using map = F <T...>;
^
Ok, quindi sembra che questo codice non è stato valido tutto questo tempo, ma gcc si è bloccato in vari modi invece di segnalare l'errore. È interessante notare che, mentre apply1
, apply2
sembrano essere equivalenti, l'errore viene registrato soltanto per apply2
(che è molto più utile nella pratica). Per quanto riguarda il clang, davvero non posso dire.
In pratica, a quanto pare non ho altro modo se non di andare avanti con gcc 4.9.0 e correggere il codice, anche se diventerà molto più complesso.
In teoria, vorrei sapere che cosa dice la norma: è questo codice valido? In caso contrario, è valido anche l'uso di apply1
? o solo apply2
?
EDIT
Giusto per chiarire che tutti i problemi che ho avuto finora si riferiscono ad alias di template, non struct modello. Ad esempio, si consideri la seguente modifica:
template <typename T> struct id1 { using type = T; };
// ...
cout << typename apply1 <id1, int>::type() << endl;
cout << typename apply2 <id1>::map <int>::type() << endl;
Questo compila bene e stampe 0
in entrambi i casi, il clangore 3.3, gcc 4.8.1, gcc 4.9.0.
Nella maggior parte dei casi, le mie soluzioni hanno introdotto un modello di struct intermedio prima l'alias. Tuttavia, ora sto cercando di utilizzare METAFUNCTIONS per parametrizzare test SFINAE generici e in questo caso devo usare gli alias direttamente, perché le strutture non devono essere istanziati. Solo per avere un'idea, un pezzo del codice attuale è here.
Il messaggio di errore del GCC 4.9 sperimentale non ha senso per me, e FWIW penso che il codice sia valido. –
correlati? http://stackoverflow.com/q/18724698/420683 – dyp
Grazie, questa domanda è correlata in quanto i modelli che trattano casi speciali come 'foo',' foo2', 'foo_variadic' ecc. sono esattamente come pensavo di correggere il codice se devo. Tuttavia, come ho modificato sopra, i miei problemi compaiono solo con gli alias del modello. – iavr