2010-05-21 19 views
7

Necesito imprimir nombres de plantillas con sangría para depuración. Por ejemplo, en lugar de una sola línea, me gustaría sangrar nombre de la siguiente manera:Nombre de la plantilla de C++ pretty print

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

empecé a escribir mi propia pero es llegar a ser complicado. ¿Existe una solución existente?

si no hay uno, ¿me pueden ayudar a terminar mi implementación? Lo publicaré si es así.

Gracias

esto es lo que parece, 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_> > > 

este es mi objetivo

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  > 

por lo que realmente puedo leer la declaración

+0

¿Dónde están estos nombres de plantilla vienen de que usted está tratando de imprimir? ¿Los está creando usted mismo, o está analizando entradas preexistentes, o ... La solución dependerá no solo de lo que está tratando de generar, sino también de dónde proviene la entrada para esta salida. –

+0

¿Cómo se correlaciona esta publicación con su respuesta a continuación? –

+1

Parece que está intentando imprimir un seguimiento de pila. Pero quiere que los tipos de plantilla se vean mejor, por lo que está buscando reemplazarlos con versiones que incluyen espaciado adicional, incluidas las líneas nuevas. –

Respuesta

1
Ciertamente no el

pieza más elegante, pero esto debería ayudarte con las etiquetas de cierre:

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

¿puedo modificar un poco tu lista? – Anycorn

+0

Si tienes mejoras menores, ponlas o en un comentario. Si tienes una versión bastante diferente, siempre puedes ponerla en otra respuesta. @aaa –

1

ajuste menor del programa GF, sobre todo, no para dividir las plantillas cortas

#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

¿Qué tal, copiar al portapapeles, a continuación,

$ xclip -o | clang-format 

Por ejemplo, esto se lleva a la plantilla de la OP a

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

No ideal, beca use hay un error en alguna parte. Pero hace que sea bastante fácil encontrar el error (el > extra después de que el void en el medio debe moverse al final). Si lo arreglamos, obtenemos

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