2010-05-21 7 views
7

J'ai besoin d'imprimer des noms de gabarits en retrait à des fins de débogage. Par exemple, au lieu d'une seule ligne, je voudrais indentez nom comme celui-ci:Nom du template C++ pretty print

boost::phoenix::actor< 
    boost::phoenix::composite< 
     boost::phoenix::less_eval, 
     boost::fusion::vector< 
     boost::phoenix::argument<0>, 
     boost::phoenix::argument<1>, 

je commencé à écrire mon propre mais commence à être compliqué. Existe-t-il une solution existante?

S'il n'y en a pas, pouvez-vous m'aider à terminer ma mise en œuvre? Je l'afficherai si c'est le cas.

Merci

c'est ce que typeid.name ressemble,

boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::less_eval, 
boost::fusion::vector<boost::phoenix::argument<0>, 
boost::phoenix::composite<boost::phoenix::multiplies_eval, 
boost::fusion::vector<boost::phoenix::argument<1>, boost::phoenix::argument<2>, 
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, 
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, 
boost::fusion::void_, boost::fusion::void >, boost::fusion::void_, 
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, 
boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, 
boost::fusion::void_> > > 

ceci est mon objectif

6 boost::phoenix::actor< 
7 boost::phoenix::composite< 
8  boost::phoenix::less_eval, 
9  boost::fusion::vector< 
10  boost::phoenix::argument<0>, 
11  boost::phoenix::composite< 
12   boost::phoenix::multiplies_eval, 
13   boost::fusion::vector< 
14   boost::phoenix::argument<1>, 
15   boost::phoenix::argument<2>, 
16   boost::fusion::void_, 
17   boost::fusion::void_, 
18   boost::fusion::void_, 
19   boost::fusion::void_, 
20   boost::fusion::void_, 
21   boost::fusion::void_, 
22   boost::fusion::void_, 
23   boost::fusion::void >, // indentation messed up 
24   boost::fusion::void_, 
25   boost::fusion::void_, 
26   boost::fusion::void_, 
27   boost::fusion::void_, 
28   boost::fusion::void_, 
29   boost::fusion::void_, 
30   boost::fusion::void_, 
31   boost::fusion::void_ 
32   > 
33  > 
34  > 

pour que je puisse réellement lire la déclaration

+0

D'où proviennent ces noms de modèles que vous essayez d'imprimer? Est-ce que vous les créez vous-même, ou que vous analysez une entrée préexistante, ou ... La solution dépend non seulement de ce que vous essayez de produire, mais aussi de l'origine de l'entrée pour cette sortie. –

+0

Comment ce post est-il corrélé avec votre réponse ci-dessous? –

+1

Il semble qu'il essaie d'imprimer une trace de pile. Mais il veut que les types de modèles soient plus beaux, alors il cherche à les remplacer par des versions qui incluent des espaces supplémentaires, y compris des retours à la ligne. –

Répondre

1

Certainement pas la pièce la plus élégante, mais cela devrait vous permettre d'aller en ce qui concerne les balises de fermeture:

std::string indent(std::string str, const std::string &indent = " ") { 
    std::string indent_ = std::string("\n"); 
    size_t token = 0; 

    while ((token = str.find_first_of("<>,", token)) != std::string::npos) { 
     switch(str[token]) { 
      case '<': indent_.append(indent); 
      case ',': str.insert(token + 1, indent_); 
         break; 
      case '>': indent_.erase(indent_.size() - indent.size()); 
         str.insert(token, indent_); 
     } 

     token += indent_.size() + 1;    
     const size_t nw = str.find_first_not_of(" ", token); 
     if(nw != std::string::npos) { 
      str.erase(token, nw-token); 
     } 
    } 

    return str; 
} 
+0

puis-je modifier légèrement votre annonce? – Anycorn

+0

Si vous avez des améliorations mineures, mettez-les ou dans un commentaire. Si vous avez une version assez différente, vous pouvez toujours la mettre dans une autre réponse. @aaa –

1

ajustement mineur du programme gf, surtout ne pas diviser courts modèles

#ifndef PRETTY_NAME_HPP 
#define PRETTY_NAME_HPP 

#include <typeinfo> 
#include <string> 
#include <iostream> 
#include <cxxabi.h> 

#define TYPENAME(TYPE) typeid_name(typeid(TYPE).name()) 

std::string indent(std::string str, const std::string &indent = " ") { 
    std::string indent_ = std::string("\n"); 
    size_t token = 0; 

    bool one_line = false; 
    while ((token = str.find_first_of("<>,", token)) != std::string::npos) { 
     size_t size = str.size(); 
     size_t close, open, comma; 

     switch(str[token]) { 
     case '<': 
      close = str.find(">", token+1); 
      open = str.find("<", token+1); 
      comma = str.find(",", token+1); 
      one_line = !(close > open) && !(comma < close); 

      if (one_line) break; 
      indent_.append(indent); 

     case ',': 
      str.insert(token + 1, indent_); 
      break; 

     case '>': 
      if (!one_line) { 
       indent_.erase(indent_.size() - indent.size()); 
       str.insert(token, indent_); 
      } 
      one_line = false; 
     } 

     token += 1 + str.size() - size; 

     const size_t nw = str.find_first_not_of(" ", token); 
     if(nw != std::string::npos) { 
      str.erase(token, nw-token); 
     } 
    } 

    return str; 
} 
std::string typeid_name(const char* name) { 
// #ifdef HAVE_CXA_DEMANGLE 
    size_t size; 
    int status; 
    char *buf = abi::__cxa_demangle(name, NULL, &size, &status); 
    if (status != 0) throw status; 
    std::string string(buf); 
    free(buf); 
    return indent(string); 
// #else 
//  return name; 
// #endif 
} 

#endif /* PRETTY_NAME_HPP */ 
1

Que diriez-vous, copier le presse-papiers, puis

$ xclip -o | clang-format 

Par exemple, cela prend le modèle de l'OP

boost::phoenix::actor < 
boost::phoenix::composite< 
    boost::phoenix::less_eval, 
    boost::fusion::vector< 
    boost::phoenix::argument<0>, 
    boost::phoenix::composite< 
     boost::phoenix::multiplies_eval, 
     boost::fusion::vector< 
     boost::phoenix::argument<1>, boost::phoenix::argument<2>, 
     boost::fusion::void_, boost::fusion::void_, 
     boost::fusion::void_, boost::fusion::void_, 
     boost::fusion::void_, boost::fusion::void_, 
     boost::fusion::void_, boost::fusion::void>, 
     boost::fusion::void_, boost::fusion::void_, 
     boost::fusion::void_, boost::fusion::void_, 
     boost::fusion::void_, boost::fusion::void_, 
     boost::fusion::void_, boost::fusion::void_> > > 

Pas idéal, parce que utiliser il y a une erreur quelque part dedans. Mais il est assez facile de trouver l'erreur (le > supplémentaire après le void au milieu devrait être déplacé à la fin). Si nous le résolvons, nous obtenons

boost::phoenix::actor<boost::phoenix::composite< 
    boost::phoenix::less_eval, 
    boost::fusion::vector< 
     boost::phoenix::argument<0>, 
     boost::phoenix::composite< 
      boost::phoenix::multiplies_eval, 
      boost::fusion::vector< 
       boost::phoenix::argument<1>, boost::phoenix::argument<2>, 
       boost::fusion::void_, boost::fusion::void_, 
       boost::fusion::void_, boost::fusion::void_, 
       boost::fusion::void_, boost::fusion::void_, 
       boost::fusion::void_, boost::fusion::void, boost::fusion::void_, 
       boost::fusion::void_, boost::fusion::void_, 
       boost::fusion::void_, boost::fusion::void_, 
       boost::fusion::void_, boost::fusion::void_, 
       boost::fusion::void_>>>>>