2010-05-21 14 views
7

Potrzebuję wydrukować nazwy wciętych szablonów do celów debugowania. Na przykład, zamiast pojedynczej linii, chciałbym, aby wciąć nazwę tak:Nazwa szablonu C++ ładna drukowana

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

zacząłem pisać własne, ale robi się być skomplikowane. Czy istnieje istniejące rozwiązanie?

jeśli go nie ma, czy możesz mi pomóc dokończyć wdrożenie? Poinformuję, jeśli tak.

Dzięki

to co typeid.name wygląda,

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

To jest mój cel

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  > 

tak, że mogę rzeczywiście przeczytać oświadczenie

+0

Skąd pochodzą nazwy szablonów, które próbujesz wydrukować? Czy tworzysz je samemu, czy analizujesz wcześniej istniejące dane wejściowe, lub ... Rozwiązanie zależy nie tylko od tego, co próbujesz wydrukować, ale także od tego, skąd pochodzi dane wejściowe dla tego wyjścia. –

+0

Jak ten wpis jest powiązany z Twoją odpowiedzią poniżej? –

+1

Wygląda na to, że próbuje wydrukować ślad stosu. Ale chce, aby typy szablonów wyglądały ładniej, więc chce zastąpić je wersjami, które zawierają dodatkowe odstępy, w tym nowe linie. –

Odpowiedz

1
pewnością nie

najbardziej elegancki element, ale powinno ci to pomóc w kwestii tagów zamykających:

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

Czy mogę nieco zmienić Twój wpis? – Anycorn

+0

Jeśli masz drobne poprawki, umieść je lub w komentarzu. Jeśli masz zupełnie inną wersję, zawsze możesz umieścić ją w innej odpowiedzi. @aaa –

1

drobne korekty programu gf, przede wszystkim, aby nie podzielić krótkie szablony

#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

Jak o, kopiowanie do schowka, a następnie

$ xclip -o | clang-format 

Na przykład ten trwa szablon PO do

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

Nie idealny, ponieważ użyj gdzieś tam błędu. Ale bardzo łatwo jest znaleźć błąd (dodatkowy > po tym, jak void w środku powinien zostać przesunięty na koniec). Jeśli go naprawimy, otrzymamy

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