2009-08-02 4 views
25

Je voudrais déboguer du code basé sur un modèle pour mieux le comprendre.
Malheureusement, je suis nouveau modèle metaprogramming et il est difficile pour moi d'entrer enMétaprogrammation de modèle C++ - Est-il possible de générer le code généré?

Lorsque je tente de sortir les fichiers source prétraitées je reçois 125 000 lignes de code:./

est là donc une comme je peux voir le code généré? (La bibliothèque que j'utilise est SeqAn)

+2

Non, mais il devrait être. Quelqu'un devrait le faire en tant que projet Clang: D –

+0

Notez qu'en raison de [SFINAE] (https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error) le code que vous obtiendriez en remplaçant simplement chaque modèle par une alternative codée en dur serait probablement illégal. Par exemple. tant qu'elle n'est jamais appelée, une méthode d'une classe modèle peut bien appeler des choses qui n'existent pas. – MvG

+1

@JosephGarvin Il existe actuellement un ou plusieurs projets basés sur Clang. La dernière version active de [Templight, le profileur et le débogueur de modèle d'instanciation clang-based] (https://github.com/mikael-s-persson/templight), [Templar visualizer] (https://github.com/ schulmar/Templar), ainsi que [Metashell] (https://github.com/sabel83/metashell). –

Répondre

21

Non, ce n'est pas le cas. Le préprocesseur n'a rien à voir avec le traitement des modèles, qui est effectué par le compilateur. Les modèles ne génèrent pas de code C++, pas plus qu'un appel de fonction - ils font partie intégrante du langage C++ lui-même.

+0

Bien que cela soit généralement vrai, c'est aussi vrai en théorie pour le préprocesseur. En pratique, l'implémentation la plus simple consiste à générer du code de type C++ en tant que sortie de l'étape du préprocesseur, mais pas pour les instanciations de modèle. L'inverse serait déraisonnablement difficile mais pas techniquement impossible. Le principal problème réside dans les recherches de noms, et le compilateur pourrait générer des noms uniques lors des instanciations de modèles. – MSalters

+0

Pour être honnête, vous pouvez toujours utiliser le débogueur pour afficher le type calculé si vous l'instanciez. J'ai fait un exemple comment utiliser Visual C++. Je l'ai très souvent utilisé pour mes méta-programmes. – ovanes

5

Ceci est potentiellement la réponse à votre question:

C++ Template preprocessor tool

semble avoir satisfait la dernière personne qui a demandé - si je ne peux pas imaginer pourquoi! La sortie d'un compilateur C++ en C est généralement assez illisible, car elle n'est pas destinée à être une aide à la compréhension, mais simplement une sorte de langage d'assemblage portable.

1

En général, il n'est pas possible de sortir le code entier. Mais ce que j'ai trouvé extrêmement intéressant, c'est la possibilité d'utiliser le débogueur Visual C++ pour vous montrer le type. Prenez ce méta-programme simple:

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; 

} 

J'ai juste instancié mes méta-types. Ce sont toujours des instances de classe C++ vides d'une longueur d'au moins 1 octet. Maintenant, je peux mettre un point d'arrêt après la dernière instanciation de test2 et voir quels types/longueur des valeurs, test1 et test2 sont de:

Voici ce que le débogueur montre:

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

Maintenant, vous savez que le head vous renvoie un caractère, votre liste contient int, double, char et se termine par null_type.

Cela m'a beaucoup aidé. Parfois, vous devez copier le type vraiment en désordre dans un éditeur de texte et le formater sous une forme lisible, mais cela vous donne la possibilité de tracer ce qui est à l'intérieur et comment il est calculé.

Espoir qui aide,
Ovanes

22

Nope, en général, il ne peut pas être fait. Les modèles font simplement partie du langage C++, ils ne sont pas un préprocesseur séparé, ils ne génèrent donc pas de code C++.

La solution habituelle consiste à saupoudrer votre code avec des assertions statiques et d'autres tests pour vérifier que les bons modèles sont instanciés de la bonne façon.

Une fois que vous commencez à se perdre dans votre métaprogrammation, cette astuce simple peut vous aider à déterminer quel type d'un paramètre de modèle est vraiment:

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

Lorsque le compilateur rencontre cela, il va imprimer une belle et simple message d'erreur, "Impossible de convertir <long, detailed typename> en int ***", vous permettant de vérifier facilement que le paramètre de template T est réellement le type que vous pensez qu'il devrait être.

14

Vérifier my publication on C++ template metaprogram debugging

De page 6, vous pouvez voir comment cela fonctionne. À des fins spécifiques, vous n'aurez pas besoin de la chaîne d'outils complète, cela peut être fait à la main.

J'ai mis en place un complément Visual C++ où vous pouviez placer des points d'arrêt, etc. mais c'était plutôt une preuve de concept qu'un outil pour une utilisation quotidienne.

Nous avons travaillé sur un frontend graphique qui montre toutes les instanciations, permet le débogage, le profilage. Malheureusement, nous ne pouvons promettre aucune date de publication pour cet outil, comme nous le faisons dans notre temps libre très limité.

MISE À JOUR: le débogueur et profileur est disponible here

MISE À JOUR: C++Now presentation

+0

Cela semble intéressant! –

Questions connexes