Название шаблона C ++ довольно печатное

Мне нужно напечатать имена шаблонов с отступом для целей отладки. Например, вместо однострочного имени я хотел бы сделать такой отступ для имени:

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

Я начал писать свой собственный, но постепенно усложняюсь. Есть ли существующее решение?

Если его нет, не могли бы вы помочь мне завершить мою реализацию? Я выложу, если так.

Спасибо

так выглядит 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_> > >

это моя цель

 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     >

так что я действительно могу прочитать декларацию


person Anycorn    schedule 21.05.2010    source источник
comment
Откуда берутся эти имена шаблонов, которые вы пытаетесь распечатать? Вы создаете их сами, или анализируете уже существующие входные данные, или ... Решение будет зависеть не только от того, что вы пытаетесь вывести, но и от того, откуда поступают входные данные для этого вывода.   -  person Jonathan M Davis    schedule 22.05.2010
comment
Как этот пост соотносится с вашим ответом ниже?   -  person Thomas Matthews    schedule 22.05.2010
comment
Похоже, он пытается распечатать трассировку стека. Но он хочет, чтобы типы шаблонов выглядели лучше, поэтому он хочет заменить их версиями с дополнительным интервалом, включая новые строки.   -  person Jonathan M Davis    schedule 22.05.2010
comment
Я бы сказал, что boost::fusion::void_, как и boost::mpl::na, на самом деле являются наполнителями (из-за отсутствия вариативных шаблонов) и логически не относятся к типу, поэтому было бы лучше их удалить (и вы тоже сэкономили бы место).   -  person Matthieu M.    schedule 22.05.2010


Ответы (3)


Конечно, не самая элегантная вещь, но это должно вас заинтересовать закрывающими тегами:

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;
}
person Georg Fritzsche    schedule 22.05.2010
comment
могу я немного изменить ваше объявление? - person Anycorn; 22.05.2010
comment
Если у вас есть незначительные улучшения, добавьте их в комментарий. Если у вас есть совсем другая версия, вы всегда можете добавить ее в другой ответ. @aaa - person Georg Fritzsche; 22.05.2010

Как насчет, скопировать в буфер обмена, а затем

$ xclip -o | clang-format

Например, это приводит к тому, что шаблон 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_> > >

Не идеально, потому что где-то там ошибка. Но это позволяет довольно легко найти ошибку (лишний > после void в середине следует переместить в конец). Если мы это исправим, то получим

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_>>>>>
person Justin L.    schedule 05.04.2016

небольшая корректировка программы gf, в основном, чтобы не разбивать короткие шаблоны

#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 */
person Anycorn    schedule 22.05.2010