2013-12-16 26 views
8

Tôi sử dụng rất nhiều mẫu và đôi khi rất khó để tìm ra mọi thứ thực sự là gì. Tôi muốn viết một tiện ích để cho tôi một cái tên đẹp, xinh xắn cho mọi kiểu - typeid() không cắt nó. Ví dụ, nếu tôi chỉ có một vector<int>, gcc.4.6.4 trên hộp của tôi tạo ra sau với typeid:Có thể lấy mẫu trên các loại HOẶC không phải loại không?

St6vectorIiSaIiEE 

trong khi tôi tưởng muốn

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

Tôi đã viết một cái gì đó mà sẽ làm việc với bất kỳ loại hay mẫu trên các loại, nhưng chỉ cung cấp hai mẫu:

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

nào khi chuyên về int hay std::vector c giúp tôi xây dựng các chuỗi tôi muốn. Tôi cũng có một chuyên môn một phần của simple_type_name chỉ trên bất kỳ Base<Args...> để đi qua tất cả các arg và làm mọi thứ khi thích hợp. Điều này làm việc hoàn toàn tốt đẹp cho intvector<int> và thực sự bất kỳ công cụ mẫu tùy ý phức tạp ... miễn là tất cả các mẫu là loại.

Nếu nó giúp, tôi phiên bản "đầy đủ mẫu" trông như thế này:

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

Câu hỏi là: làm thế nào để tôi làm những gì tôi đã làm việc cho, nói, std::array<int, 10>? Tôi không biết cách xử lý các tham số không kiểu. Điều này thậm chí có thể?

+4

"Tôi sử dụng rất nhiều mẫu và đôi khi rất khó để tìm ra mọi thứ thực sự là gì." Tôi yêu C++ –

+0

Tôi nhớ rằng phải có một chức năng có sẵn (ít nhất là đối với GCC) có thể phá vỡ tên 'typeid() .' cho bạn. –

+2

Bạn đã thử sử dụng 'C++ filt' để bỏ ẩn tên không? – greatwolf

Trả lời

3

Một phiên bản phần nào dễ dàng hơn demangle với một số giấy gói tiện theo dõi:

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

cho phép bạn sử dụng:

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

trực tiếp để xem thực tế là T.

7

Nếu bạn muốn có một g ++ demangle cụ thể:

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

(Thêm một try/catch - Nhờ Daniel Frey)

Các vấn đề liên quan