2009-08-02 15 views
25

Vorrei eseguire il debug di un codice basato su modelli per comprenderlo meglio.
Purtroppo Sono nuovo di modello metaprogrammazione ed è difficile per me arrivare inModello C++ Metaprogrammazione - È possibile generare il codice generato?

Quando cerco di uscita i file di origine preprocessati ottengo 125 000 righe di codice:./

è così c'è un modo in cui posso vedere il codice generato? (La libreria che sto utilizzando è SeqAn)

+2

No, ma dovrebbe essere. Qualcuno dovrebbe farlo come un progetto Clang: D –

+0

Si noti che a causa di [SFINAE] (https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error) il codice che si ottiene semplicemente sostituendo ogni modello con qualche alternativa hardcoded sarebbe probabilmente illegale. Per esempio. finché non viene mai chiamato, un metodo di una classe template potrebbe chiamare cose che non esistono. – MvG

+1

@JosephGarvin C'è un progetto Clang a base di (s) per questo ora. L'ultima versione attiva di [Templight, il template per la creazione di istanze di template clang e il debugger] (https://github.com/mikael-s-persson/templight), [Templar visualizer] (https://github.com/) schulmar/Templari), così come [Metashell] (https://github.com/sabel83/metashell). –

risposta

21

No, non lo è. Il preprocessore non ha nulla a che fare con l'elaborazione dei template, che viene eseguita dal compilatore. I template non generano codice C++, più di quanto non faccia una chiamata di funzione - sono parte integrante del linguaggio C++ stesso.

+0

Mentre questo è vero in generale, è in teoria anche per il preprocessore. In pratica, l'implementazione più semplice è generare codice simile a C++ come output dello stage del preprocessore, ma non per le istanze dei template. Il contrario sarebbe irragionevolmente difficile ma non tecnicamente impossibile. Il problema principale è nelle ricerche dei nomi e il compilatore può generare nomi univoci durante le istanze del modello. – MSalters

+0

Per essere onesti è ancora possibile utilizzare il debugger per mostrare il tipo calcolato se si crea un'istanza di esso. Ho fatto un esempio su come utilizzare Visual C++. L'ho usato molto spesso per i miei meta-programmi. – ovanes

5

Questo è potenzialmente la risposta alla tua domanda:

C++ Template preprocessor tool

sembra aver soddisfatto l'ultima persona che ha chiesto - anche se non riesco a immaginare perché! L'output di un compilatore C++ in C è in genere piuttosto illeggibile, perché non è inteso come aiuto alla comprensione, ma solo una sorta di linguaggio assembly portatile.

1

in generale non è possibile stampare l'intero codice. Ma quello che ho trovato estremamente interessante, è la possibilità di usare il debugger di Visual C++ per mostrarti il ​​tipo. Prendi questo semplice meta-programma:

template<class Head, class Tail> 
struct type_list 
{ 
    typedef Head head; 
    typedef Tail tail; 
}; 

struct null_type 
{}; 

template<class List> 
struct list_head 
{ 
    typedef typename List::head head; 
}; 

template<class List> 
struct list_tail 
{ 
    typedef typename List::tail tail; 
}; 

template<class List> 
struct list_length 
{ 
    static const size_t length = 1+list_length< typename list_tail<List>::tail >::length; 
}; 

template<> 
struct list_length<null_type> 
{ 
    static const size_t length = 0; 
}; 


int main() 
{ 
    typedef 
    type_list 
    < int 
    , type_list 
     < double 
     , type_list 
     < char 
     , null_type 
     > 
     > 
    >  my_types; 

    my_types test1; 

    size_t length=list_length<my_types>::length; 

    list_head<list_tail<list_tail<my_types>::tail>::tail>::head test2; 

} 

Ho appena creato un'istanza dei miei meta-tipi. Queste sono istanze di classe C++ ancora vuote che hanno una lunghezza di almeno 1 byte. Ora posso mettere un punto di interruzione dopo l'ultima istanza di test2 e vedere, quali tipi/valori di lunghezza, test1 e test2 sono di:

Ecco ciò che il debugger mostra:

length 3 unsigned int 
test1 {...} type_list<int,type_list<double,type_list<char,null_type> > > 
test2 -52 'Ì' char 

Ora si conosce il head ti ha restituito un carattere, la tua lista contiene int, double, char e termina con null_type.

Questo mi ha aiutato molto. A volte è necessario copiare il tipo veramente disordinato in un editor di testo e formattarlo in un formato leggibile, ma ciò ti dà la possibilità di rintracciare ciò che è dentro e come viene calcolato.

Speranza che aiuta,
Ovanes

22

No, in generale, non può essere fatto. I template sono semplicemente parte del linguaggio C++, non sono un preprocessore separato, quindi non generano codice C++.

La solita soluzione consiste nel cospargere il codice con affermazioni statiche e altri test per verificare che i modelli giusti vengano istanziati nei giusti modi.

Una volta che si inizia a perdersi nel vostro metaprogrammazione, questo semplice trucco può aiutare a determinare quale tipo un parametro di modello è davvero:

// given a variable t of an unknown type T 
int*** i = t; 

Quando il compilatore incontra questo, sarà stampare una piacevole e semplice messaggio di errore, "Impossibile convertire <long, detailed typename> in int ***", consentendo di verificare facilmente che il parametro modello T sia effettivamente il tipo che si ritiene dovrebbe essere.

14

check my publication on C++ template metaprogram debugging

Da pagina 6 si può vedere come funziona. Per scopi specifici non avrai bisogno dell'intera toolchain, può essere fatto a mano.

ho messo insieme un Visual C++ aggiuntivo in cui è possibile inserire punti di interruzione ecc ma era piuttosto una prova di concetto che uno strumento per un utilizzo quotidiano.

Abbiamo lavorato su un frontend grafico che mostra tutte le istanze, permette il debug, profiling. Purtroppo non possiamo promettere alcuna data di pubblicazione per questo strumento, poiché lo facciamo nel nostro tempo libero piuttosto limitato.

UPDATE: il debugger e profiler è disponibile here

UPDATE: C++Now presentation

+0

Sembra interessante! –

Problemi correlati