2013-09-27 34 views
18

Sto lavorando a un'infrastruttura software su larga scala in C++ 11 che fa ampio uso di modelli variadici. La mia domanda è la seguente: qual è la scalabilità di questo approccio? Innanzitutto, esiste un limite superiore nel numero di argomenti che i modelli variadic possono assumere? In secondo luogo, il codice gonfia un grosso problema con i compilatori di ultima generazione quando vengono utilizzati molti argomenti (e, per estensione, molte combinazioni di questi argomenti che potrebbero cedere a molte diverse implementazioni dei metodi basati su modelli)?Scalabilità di modelli variadici

+10

In teoria non ci sono limiti, ma ovviamente c'è un limite nella pratica, dettato da alcune risorse limitate come la RAM. Se arrivi ad un punto in cui quel limite conta, probabilmente hai problemi più grandi, quindi non mi preoccuperei di quello. –

+3

La seconda domanda è difficile da rispondere, perché dipende più dal resto del codice che dall'esatto numero di argomenti del modello esistenti. Se si utilizzano molti argomenti del modello per calcolare il tempo di compilazione del materiale, potrebbe non esserci alcun codice generato. Altrimenti, se il codice viene generato, il numero di istanze sarà un fattore moltiplicativo. Questo non è diverso dai modelli non-variadici. –

+12

L'allegato B (quantità di implementazione), della norma C++ 11 non dice nulla in particolare sui modelli * variadic *, ma raccomanda almeno 256 parametri di funzione e 1024 parametri di modello. Tuttavia, potresti riscontrare dei problemi in precedenza quando i tuoi nomi storti diventano troppo lunghi. – Oberon

risposta

10

Ho pensato di provare a stabilire se esiste un limite al numero di parametri del modello per il mio particolare compilatore (g ++ 4.8.1 su Linux). Ho usato il seguente test case:

template <int I> 
struct this_is_a_ridiculously_long_struct_name_youd_never_use_in_real_life {}; 

template <int Depth, typename... T> 
struct A 
{ 
    using e = this_is_a_ridiculously_long_struct_name_youd_never_use_in_real_life<Depth>; 

    A() {}; 

    A<Depth - 1, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, e, T...> a; 
}; 

template <typename... T> 
struct A<0, T...> 
{ 
}; 

int main() 
{ 
    A<899> a; 
} 

il modello di ricorsione limite di profondità di default a 900 in g ++, da qui il 899 parametro che si vede. Il nome della struttura ridicolmente lungo è usato per vedere se potrei generare simboli troppo grandi per il linker da gestire - più su questo in un secondo.

Nel caso in cui non è possibile vedere cosa sta succedendo nel test case, in pratica ogni istanziazione di A crea una variabile membro che aggiunge 20 parametri di modello aggiuntivi. La specializzazione parziale viene utilizzata per interrompere la ricorsione. Alla fine, A<0, ...> ha una posizione nella regione di 18000 parametri del modello.

Quello che ho trovato è che g ++ ha gestito questo bene. Ci è voluto un po 'per pensarci, e ho usato un bel po' di memoria, ma non sono riuscito a farlo fallire semplicemente aumentando il numero di parametri del template. Clang 3.1 ha gestito anche questo senza alcun problema una volta che la profondità di ricorsione del modello è stata impostata sufficientemente (cioè 900).

Inoltre, anche se i nomi dei simboli storti sono davvero enormi, non sono riuscito a rompere né nmld utilizzandoli. (Vale la pena notare che lo schema di mangling di Linux/Itanium utilizza la sostituzione in modo che i parametri ripetuti del modello dello stesso tipo non ripetano l'intero nome del tipo, ma piuttosto che siano contrassegnati S0, S1 ecc.) Un google veloce non sembra girare fino a un limite di lunghezza del simbolo ELF, ma forse qualcun altro sa se esiste un limite di questo tipo.

In conclusione quindi, per g ++ e clang su Linux almeno, non sembra esserci alcun limite pratico al numero di parametri modello.

Per quanto riguarda la seconda parte della domanda, per quanto riguarda il codice gonfiato, è molto difficile da dire, in particolare una volta coinvolta l'ottimizzazione del compilatore. È facile fare la ricorsione con i modelli variadici, ma poi è facile per il compilatore eliminare anche i tipi intermedi. Posso solo suggerire di provarlo e vedere.

+0

Il numero di argomenti del modello che stavo usando (nel codice generato) dipendeva dal cliente e quindi era senza limiti. Quindi la mia risposta suggerisce di usare boost :: mpl che evita questa limitazione. –

Problemi correlati