C ++ nombre de la plantilla impresión bonita
Pregunta
Tengo que imprimir nombres de plantilla con sangría para fines de depuración. Por ejemplo, en lugar de una sola línea, me gustaría nombre guión de esta manera:
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. ¿Hay una solución existente?
Si no hay uno, ¿me pueden ayudar a terminar mi aplicación? Voy a publicar que de ser así.
Gracias
Esto es lo que se ve como 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
Solución
Desde luego, no la pieza más elegante, pero esto debe conseguir que ir en relación 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;
}
Otros consejos
ajuste menor del programa GF, principalmente no 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 */
¿Qué tal, copiar al portapapeles, a continuación,
$ xclip -o | clang-format
Por ejemplo, esto se lleva de la OP plantilla 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 es ideal, porque hay un error en alguna parte en el mismo. Pero hace que sea muy fácil encontrar el error (la >
extra después de la void
en el medio debe ser trasladado hasta el 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_>>>>>