可以在类型或非类型上进行模板化吗?

Bar*_*rry 8 c++ templates c++11

我使用了很多模板,偶尔很难弄清楚究竟是什么类型的.我想编写一个实用程序,为每个类型提供一个漂亮,漂亮的字符串名称 - typeid()只是不切割它.例如,如果我只有一个vector<int>,我的盒子上的gcc.4.6.4会生成以下带有typeid:

St6vectorIiSaIiEE
Run Code Online (Sandbox Code Playgroud)

虽然我理想的想要

std::vector<
    int,
    std::allocator<
        int
    >
>
Run Code Online (Sandbox Code Playgroud)

我已经编写了可以在类型上使用任何类型或模板的东西,但只提供了两个模板:

template <typename T> struct simple_type_name;
template <template <typename....> class T> struct template_type_name;
Run Code Online (Sandbox Code Playgroud)

哪些专业intstd::vector可以帮助我建立我想要的字符串.我还有一个部分专业化,simple_type_nameBase<Args...>需要遍历所有的args并做适当的事情.只要所有模板都是类型,这对于intvector<int>任何任意复杂的模板来说都是完全正常的.

如果有帮助,我的"完整模板"版本如下所示:

template <template <typename...> class Base, typename... Args>
struct simple_type_name<Base<Args...>>
{
    static std::string name(int indent = 0) {
        std::string base = template_type_name<Base>::name(indent);
        std::string args[] = { simple_type_name<Args>::name(indent + 4)... } ;

        // basic string putting together stuff here that is less interesting
    }
};
Run Code Online (Sandbox Code Playgroud)

问题是:我怎么做我的工作,比方说呢std::array<int, 10>?我不知道如何处理非类型参数.这甚至可能吗?

小智 7

如果你想要一个特定于g ++的demangle:

#include <iostream>
#include <typeinfo>
#include <cxxabi.h>

std::string demangle(const std::string& source_name)
{
    std::string result;
    size_t size = 4096;
    // __cxa_demangle may realloc()
    char* name = static_cast<char*>(malloc(size));
    try {
        int status;
        char* demangle = abi::__cxa_demangle(source_name.c_str(), name, &size, &status);
        if(demangle) result = demangle;
        else result = source_name;
    }
    catch(...) {}
    free(name);
    return result;
}

template <typename T, int I> struct X {};
int main()
{
    // Prints: X<int, 0>
    std::cout << demangle(typeid(X<int, 0>).name()) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

(添加了试试/捕获 - 感谢Daniel Frey)


Dan*_*rey 3

一个更简单的版本,demangle带有一些方便的包装器:

#include <string>
#include <memory>
#include <typeinfo>
#include <cxxabi.h>

std::string demangle( const char* symbol )
{
    const std::unique_ptr< char, decltype( &std::free ) > demangled( abi::__cxa_demangle( symbol, 0, 0, 0 ), &std::free );
    return demangled ? demangled : symbol;
}

std::string demangle( const std::string& symbol )
{
    return demangle( symbol.c_str() );
}

std::string demangle( const std::type_info& ti )
{
    return demangle( ti.name() );
}
Run Code Online (Sandbox Code Playgroud)

它允许您使用:

std::cout << demangle( typeid( T ) ) << std::endl;
Run Code Online (Sandbox Code Playgroud)

直接看看T到底是什么。