2011-01-16 23 views
15

Continuando con my journey into the world of variadic templates, ho riscontrato un altro problema.Specializzazione modello parziale con più pacchetti di parametri modello

Assumendo la seguente classe template:

template < typename T > 
struct foo 
{ 
    //default implementation 
}; 

è possibile specializzarsi in parte per istanze di template variadic come questo:

template < template < typename ... > class T, typename ...Args > 
struct foo< T<Args...> > 
{ 
    //specialized implementation 
}; 

Con questo, foo<int> corrisponderà alla implementazione predefinita e foo< std::tuple< int, char > > all'attuazione specializzata.

Tuttavia, le cose diventano più complicate quando si utilizzano diversi parametri del modello. Per esempio, se abbiamo la seguente classe template

template < typename T, typename U > 
struct bar {}; 

e vogliamo specializzarsi in parte come abbiamo fatto per foo, non possiamo fare

template < template < typename ... > class T, typename ...TArgs, 
      template < typename ... > class U, typename ...UArgs > 
struct bar< T<TArgs...>, U<UArgs...> > {}; 

//This would correspond to the specialized version with 
//T=std::tuple, 
//TArgs=int,char 
//U=std::tuple, 
//UArgs=float 
bar< std::tuple< int, char >, std::tuple<float> > b; 

Anzi, se non sbaglio, possiamo solo avere un pacchetto di parametri template e deve essere posizionato alla fine dell'elenco dei parametri. Capisco perché questo sia obbligatorio nelle dichiarazioni dei modelli, ma per alcune specializzazioni di template parziali (come nell'esempio sopra), questo non dovrebbe essere un problema.

È possibile ottenere una specializzazione del modello parziale con più pacchetti di parametri modello?


Edit: Ora mi sento stupido ... il codice che ho dato sopra compila perfettamente (almeno con gcc 4.5). L'errore di compilazione che avevo non era dovuto a più pacchetti di parametri, ma a causa del loro utilizzo come parametri delle funzioni membro. Nella specializzazione parziale di bar, ho cercato di definire una funzione membro che prende sia TArgs e UArgs parametri:

template < template < typename ... > class T, typename ...TArgs, 
      template < typename ... > class U, typename ...UArgs > 
struct bar< T<TArgs...>, U<UArgs...> > 
{ 
    void method(TArgs... targs, UArgs... uargs) //compile error here 
    { 
    } 
}; 

Nella dichiarazione funzione membro, gcc mi dà l'errore

parametri pacchi devono essere alla fine della lista dei parametri.

Per quanto posso dire, il compilatore dovrebbe essere in grado di definire la funzione membro corretta per una data istanziazione di modello, ad es. bar< std::tuple< int, char >, std::tuple<float> > dovrebbe contenere una funzione membro void method(int, char, float). Sto facendo qualcosa di sbagliato? O sto cercando di fare qualcosa che non è possibile? Se è così, c'è una buona ragione per cui questo non è possibile?

+0

Neat, non sapevo che potresti specializzare/specificare (parte) gli elementi di un elenco di modelli come modelli stessi. – JAB

risposta

6

Probabilmente questa risposta non risolverà la tua domanda direttamente, ma il seguente codice è stato compilato su ideone (gcc-4.5.1) quando ho provato.

#include <cstdio> 
#include <tuple> 

template< class, class > struct S { 
    S() { puts("primary"); } 
}; 

template< 
    template<class...> class T, class...TArgs 
, template<class...> class U, class...UArgs 
> 
struct S< T<TArgs...>, U<UArgs...> > { 
    S() { puts("specialized"); } 
}; 

int main() 
{ 
    S< int, int > p;          // "primary" 
    S< std::tuple< int, char >, std::tuple<float> > s; // "specialised" 
} 

Non sono sicuro che questo codice è strettamente conforme, ma per quanto ho letto N3225 14.5.3, non riuscivo a trovare la dichiarazione che menziona quel parametro Template Pack deve essere l'ultimo modello parametro.

Modifica:
ho riletto N3225 ed ha trovato le seguenti dichiarazioni:

8.3.5/4 Se il parametro-dichiarazione-clausola termina con i puntini di sospensione o di un parametro pacchetto funzione (14.5.3), il numero di argomenti deve essere uguale a o superiore al numero di parametri che non hanno un argomento predefinito e non sono funzionali ai pacchetti di parametri .

14.8.2.5/10 [Nota: un pacchetto di parametri funzione può essere eseguito solo alla fine di una lista di dichiarazione dei parametri (8.3.5). -end nota]

Quindi, come lei ha ricordato, il parametro funzione pack deve essere l'ultimo parametro purtroppo.
Una funzione membro non di modello di un modello di classe è una funzione ordinaria per quella classe quando viene creata un'istanza (completamente specializzata). Quindi mi auguro che il codice in questa domanda possa essere compilato logicamente, come un caso speciale .

+0

Hai ragione, il codice si compila perfettamente! Il problema che aggiungo è in realtà un po 'diverso, modifico la domanda ... Ci scusiamo per l'inconveniente ... –

+0

@LucTouraille: Non preoccuparti :-) Questa è stata una buona occasione educativa per me. –

+0

Qualcosa mi fa pensare che la citazione non è pensata per essere applicata qui perché entrambi i pacchetti di parametri sono già noti e devono solo essere espansi. non mi sorprenderebbe se clang accetterebbe questo codice –

Problemi correlati