2013-12-16 122 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 - 感謝丹尼爾·弗雷)