2013-12-16 123 views
8

我使用了很多模板,偶尔很难弄清究竟是什么类型的东西。我想写一个实用程序给我一个漂亮的,漂亮的字符串名称,每种类型 - typeid()只是不削减它。举例来说,如果我有一个vector<int>,在我的箱子gcc.4.6.4产生与typeid的以下内容:可能模板类型或非类型?

St6vectorIiSaIiEE 

而我最好要

std::vector< 
    int, 
    std::allocator< 
     int 
    > 
> 

我写的东西,将工作与任何类型或类型的模板,但只是提供了两个模板:

template <typename T> struct simple_type_name; 
template <template <typename....> class T> struct template_type_name; 

哪个专业上intstd::vector c当帮助我建立我想要的琴弦。我也有部分专业simple_type_name在任何Base<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 
    } 
}; 

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

+4

“我使用了很多模板,偶尔很难弄清究竟是什么类型的东西。”我爱C++ –

+0

我记得应该有一个可用的函数(至少对于GCC),它可以为你的'typeid()。name'取消。 –

+2

您是否尝试过使用'C++ filt'来取消名字? – greatwolf

回答

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()); 
} 

,它允许您使用:

std::cout << demangle(typeid(T)) << std::endl; 

直接看什么T实际上是。

7

如果你想有一个G ++特定的还原函数:

#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; 
} 

(由一个try/catch - 感谢丹尼尔·弗雷)