10

Dato un metaprogramma modello (TMP), i compilatori C++ producono statistiche di compilazione che contano il numero di classi istanziate? O c'è un altro modo per ottenere automaticamente questo numero? Quindi per es. il obiquitous fattorialeConta automaticamente il numero di classi istanziate in un TMP?

#include <iostream> 

template<int N> struct fact { enum { value = N * fact<N-1>::value }; }; 
template<> struct fact<1> { enum { value = 1 }; }; 

int main() 
{ 
    const int x = fact<3>::value; 
    std::cout << x << "\n"; 
    return 0; 
} 

Vorrei tornare al numero 3 (dal fatto < 3>, infatti < 2>, e infatti < 1> vengono istanziati). Questo esempio è ovviamente banale, ma ogni volta che inizi a utilizzare per es. Boost.MPL, i tempi di compilazione esplodono davvero, e mi piacerebbe sapere quanto sia dovuto a istanze di classe nascoste. La mia domanda è principalmente per Visual C++, ma anche le risposte per gcc sarebbero apprezzate.

EDIT: il mio attuale approccio molto fragile per Visual C++ sta aggiungendo lo switch di compilazione di uno dei di Stephan T. Lavavej videos/d1reportAllClassLayout e facendo un conteggio di grep + parola sulla file di output, ma (a) aumenti di compilazione tempi enormi e (b) la regex è difficile da ottenere corretta al 100%.

risposta

7

Ho creato un GAP one-line change che consente di stampare il nome di ogni modello di classe durante la sua istanziazione. È già possibile chiamare il front-end C++ cc1plus direttamente senza il flag -quiet per ottenere lo stesso risultato per i modelli di funzione.

Non ho ancora finito di trasformarlo in un'opzione GCC corretta, è solo un hack sul mio albero dei sorgenti. Sto pensando di implementarlo come un plugin, ma non è vicino alla parte superiore della mia lista TODO.

+0

+1. Ho suggerito che dovrebbe essere abbastanza facile hackerare qualsiasi compilatore open source, ma in realtà lo hai dimostrato, nel miglior modo possibile (scrivendo una patch che effettivamente lo fa). – abarnert

+0

Grazie! Ciò che sarebbe anche più conveniente avere (sì, scope creep in arrivo!) È un log di tutti i modelli di classe e il numero delle loro istanziazioni, piuttosto che solo il numero totale o l'intero elenco di tutte le istanze. Forse uno script perl per post-processare il log di compilazione completo è quello che dovrei provare. – TemplateRex

+1

invia l'output a 'awk -F '<' '{templates [$ 1] ++} END {per (t nei modelli) print t, templates [t]}'' –

2

Non c'è, ovviamente, un modo portatile per farlo.

Esistono modi hacky per farlo per la maggior parte dei compilatori. Ne hai già trovato uno per MSVC. Per gcc, puoi probabilmente usare gccxml. Oppure, per qualsiasi compilatore open source (gcc o clang), dovrebbe essere piuttosto semplice aggiungere codice nel punto di istanziazione che tiene il conto o registra qualcosa che puoi filtrare dopo aver completato la compilazione.

Per Clang/LLVM, è possibile semplicemente creare un plug-in che aggancia l'istanziazione, che è molto più pulito, ma probabilmente in realtà più lavoro.

Una build con simboli di debug, nessuna ottimizzazione e nessuna spaziatura potrebbero finire con i nomi storpiati di ogni istanza, che è possibile per grep. Tuttavia, alcuni compilatori (incluso gcc) inseriranno sempre almeno alcuni metodi, che lo si voglia o no. Se siete disposti a modificare il codice, probabilmente si può costringerlo a generare istanze out-of-line, forse qualcosa di simile:

template<int N> struct fact { 
    enum { value = N * fact<N-1>::value }; 
    int *dummy() { return &fact<N-1>::value; } 
}; 
+0

Grazie!La modifica del codice non è realmente un'opzione perché il 99% dei modelli di classi istanziate proviene da Boost.MPL e ecc. E voglio avere un conteggio pulito anche di quelli. – TemplateRex

+0

Credo che MSVC possa essere impostato per disattivare assolutamente tutte le inlining e l'ottimizzazione, il che significa che otterrete un'istanza fuori linea per tutto, ma non penso che nessun altro compilatore abbia tali impostazioni. – abarnert

1

v'è uno strumento scritto da Steven Watanabe che può essere utilizzato per contare il numero di istanze del modello. Puoi ottenerlo here. Fondamentalmente, modifica il codice in modo che venga generato un avviso del compilatore ogni volta che viene creata un'istanza e quindi è possibile elaborare il testo risultante con espressioni regex, ad esempio.

+0

Grazie, ci provo. – TemplateRex