2010-05-21 6 views
7

Ho bisogno di stampare i nomi dei template rientrati a scopo di debug. Ad esempio, invece di una sola linea, vorrei rientrare nome come questo:Nome modello C++ pretty print

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

ho iniziato a scrivere il mio, ma è di arrivare a essere complicato. Esiste una soluzione esistente?

se non ce n'è uno, puoi aiutarmi a finire la mia implementazione? Lo posterò in questo caso.

Grazie

questo è ciò che sembra, typeid.name

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_> > > 

questo è il mio obiettivo

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  > 

modo che io possa effettivamente letto dichiarazione

+0

Dove provengono questi nomi modello che stai cercando di stampare? Li stai creando tu stesso, o stai analizzando input preesistenti, o ... La soluzione dipenderà non solo da ciò che stai cercando di produrre, ma anche da dove proviene l'input per questa uscita. –

+0

In che modo questo post è correlato alla tua risposta qui sotto? –

+1

Sembra che stia cercando di stampare una traccia dello stack. Ma vuole che i tipi di template sembrino più belli, quindi sta cercando di sostituirli con versioni che includono spaziatura extra, incluse le newline. –

risposta

1
non il

Certamente pezzo più elegante, ma questo dovrebbe farti andare in merito ai tag di chiusura:

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

posso modificare leggermente la tua inserzione? – Anycorn

+0

Se hai piccoli miglioramenti, inseriscili o in un commento. Se hai una versione abbastanza diversa puoi sempre inserirla in un'altra risposta. @aaa –

1

piccola regolazione del programma di GF, soprattutto per non dividere i modelli brevi

#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

ne dite, copiare negli appunti, quindi

$ xclip -o | clang-format 

Ad esempio, questo richiede modello del PO per

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_> > > 

Non ideale, perché usa c'è un errore da qualche parte in esso. Ma rende abbastanza facile trovare l'errore (ilin più dopo il void nel mezzo dovrebbe essere spostato alla fine). Se lo aggiustiamo, otteniamo

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_>>>>>